Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Performance SQRT Calculations

I have this code:

package math;

import java.io.IOException;
import java.util.Scanner;

public class Main
{
    public static void main(String[] args) throws IOException
    {
        System.out.println("Hi, I will beat Java's Math.sqrt(double) method");
        System.out.println("Both ways of calculation will be done");
        System.out.println("I will time how long they took to calculate");
        System.out.println("Random doubles will be generated");
        System.out.println();
        System.out.println("Please give the number of sqrt-calculation will be done");
        int calcs = new Scanner(System.in).nextInt();
        boolean output = true;
        if (calcs > 10000)
        {
            System.out.println("You're asking much calculations");
            System.out.println("Disabling output is recommend");
            System.out.println("Disable output? (y/n)");
            char a = (char) System.in.read();
            if (a == 'y')
            {
                output = false;
            }
        }
        System.out.println("Press enter to start");
        System.in.read();
        test(calcs, output);
        System.out.println();
        System.out.println("I was much faster I think");
        System.out.println("Now you can check my precision");
        System.out.println("Please give a complex double");
        double x = Double.parseDouble(new Scanner(System.in).next());
        System.out.println();
        System.out.println("Math.sqrt(" + x + ")           = " + Math.sqrt(x));
        System.out.println("SqrtCalculator.sqrt(" + x + ") = " + sqrt(x));
        System.out.println("------------------------");
        System.out.println("Now please make your conclusion");
        System.out.println("Thanks for trying");
    }

    public static void test(int calculations, boolean output)
    {
        double factor = Math.random() / 2;
        // Math
        long mathStart = System.currentTimeMillis();
        for (int i = 1; i <= calculations; i++)
        {
            double x = i * factor;
            double result = Math.sqrt(x);
            if (output)
            {
                System.out.println("Math.sqrt(" + x + ") =  " + result);
            }
        }
        long mathStop = System.currentTimeMillis();
        long mathTime = mathStop - mathStart;
        // My Method
        long myStart = System.currentTimeMillis();
        for (int i = 1; i <= calculations; i++)
        {
            double x = i * factor;
            double result = sqrt(x);
            if (output)
            {
                System.out.println("SqrtCalculater.sqrt(" + x + ") =  " + result);
            }
        }
        long myStop = System.currentTimeMillis();
        long myTime = myStop - myStart;
        System.out.println();
        if (output)
            System.out.println("---------------------------");
        System.out.println("Here are the results:");
        System.out.println("Math and SqrtCalculator did each " + calculations + " of the same sqrt-calculations");
        System.out.println();
        System.out.println("Math: " + mathTime + " milliseconds");
        System.out.println("I:    " + myTime + " milliseconds");
    }

    public final static double sqrt(double x)
    {
        double previous = 1;
        double now = 0;
        for (;;)
        {
            now = (x / previous + previous) / 2;
            if (previous == now)
            {
                return now;
            }
            previous = now;
        }
    }
}

This sqrt method is called "heroon".
If I run my program and I ask 80000 calculations and I disable the output, Math.sqrt() is much faster than my method. If I ask 80000 calcs and I enable the output, My method is much faster.

Can someone explain this?

Thanks

Sorry for bad English.

like image 584
Martijn Courteaux Avatar asked May 29 '26 08:05

Martijn Courteaux


2 Answers

I could not reproduce your results. Tried some times using Eclipse Galileo and JDK 1.6.0.

For 80000, output disabled, I got something like:

Math: 15 milliseconds
I:    32 milliseconds

small times, It would be better to use System.nanoTime() or more interactions.

For 80000, output enabled:

Math: 3609 milliseconds
I:    4906 milliseconds

So probably the problem is the way that output is handled (scrolling, buffering, ...)

like image 60
user85421 Avatar answered May 31 '26 22:05

user85421


The Math.sqrt method defers to StrictMath.sqrt, which is done in hardware or native code. (Look at the source for the JDK - you'll see that it's a native method.) This is certainly faster than anything you'll write. It might even be using the same algorithm that you coded. It's well known. Your method is simply Newton's method for calculating square roots. It's been known since Babylon; Newton simply rederived it using calculus. Quadratic convergence is good.

Whatever you've done, it's unlikely that you've discovered anything new or noteworthy. Sounds like something having to do with IO is artificially biasing the results.

like image 23
duffymo Avatar answered May 31 '26 21:05

duffymo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!