My code:
import java.math.BigDecimal;
public class ScienceFair {
private static long NewtonMethod()
{
BigDecimal TWO = new BigDecimal(2);
BigDecimal SQRT_TWO = new BigDecimal("1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727");
BigDecimal TOLERANCE = BigDecimal.ONE.scaleByPowerOfTen(-100);
long start = System.nanoTime();
BigDecimal a = new BigDecimal(1);
while(a.subtract(SQRT_TWO).abs().compareTo(TOLERANCE) >= 0) {
a = a.add(TWO.divide(a, 100, BigDecimal.ROUND_HALF_UP)).divide(TWO);
}
return System.nanoTime() - start;
}
private static long MidpointMethod()
{
BigDecimal TWO = new BigDecimal(2);
BigDecimal SQRT_TWO = new BigDecimal("1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727");
BigDecimal TOLERANCE = BigDecimal.ONE.scaleByPowerOfTen(-100);
long start = System.nanoTime();
BigDecimal a = new BigDecimal(1);
BigDecimal b = new BigDecimal(2);
while(a.add(b).divide(TWO).subtract(SQRT_TWO).abs().compareTo(TOLERANCE) >= 0) {
if(a.multiply(a).subtract(TWO).abs().compareTo(b.multiply(b).subtract(TWO).abs()) == 1)
{
a = a.add(b).divide(TWO);
}
else
{
b = a.add(b).divide(TWO);
}
}
return System.nanoTime() - start;
}
private static long SecantMethod()
{
BigDecimal TWO = new BigDecimal(2);
BigDecimal SQRT_TWO = new BigDecimal("1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727");
BigDecimal TOLERANCE = BigDecimal.ONE.scaleByPowerOfTen(-100);
long start = System.nanoTime();
BigDecimal a = new BigDecimal(1);
BigDecimal b = new BigDecimal(2);
BigDecimal b_old = new BigDecimal(2);
while(a.add(b).divide(TWO).subtract(SQRT_TWO).abs().compareTo(TOLERANCE) >= 0) {
b_old = b;
b = a.multiply(b).add(TWO).divide(a.add(b), 100, BigDecimal.ROUND_HALF_UP);
a = b_old;
}
return System.nanoTime() - start;
}
public static void main(String[] args) {
double a = 0;
int trials = 100;
for(int i=1; i<= trials; i++)
{
a += (NewtonMethod() / 10e6);
}
System.out.printf("Newton's Method: %f\n", a/trials);
a = 0;
for(int i=1; i<= trials; i++)
{
a += (MidpointMethod() / 10e6);
}
System.out.printf("Midpoint Method: %f\n", a/trials);
a = 0;
for(int i=1; i<= trials; i++)
{
a += (SecantMethod() / 10e6);
}
System.out.printf("Secant Method: %f\n", a/trials);
}
}
is designed to run the Newton Method, the Midpoint Method, and the Secant Method to find the amount of time it takes to approximate the square root of two to 100 decimal places.
It runs 100 trials of each of them, and averages them to output the number of milliseconds taken.
The Midpoint method is always around 1.5 seconds. However, the Newton method and the Secant method vary greatly, ranging from 0.08 to 0.14 seconds (about double). Why is this happening?
Edit: Here is what I tried now (only for NewtonMethod)
public class ScienceFairTwo {
public static void main(String[] args) throws Exception {
Runnable NewtonMethod = new Runnable()
{
public void run()
{
BigDecimal TWO = new BigDecimal(2);
BigDecimal SQRT_TWO = new BigDecimal("1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727");
BigDecimal TOLERANCE = BigDecimal.ONE.scaleByPowerOfTen(-100);
long start = System.nanoTime();
BigDecimal a = new BigDecimal(1);
while(a.subtract(SQRT_TWO).abs().compareTo(TOLERANCE) >= 0) {
a = a.add(TWO.divide(a, 100, BigDecimal.ROUND_HALF_UP)).divide(TWO);
}
}
};
System.out.println("Newton's Method: " + new Benchmark(NewtonMethod));
}
}