Java:性能SQRT计算

Java:性能SQRT计算,java,performance,math,sqrt,Java,Performance,Math,Sqrt,我有以下代码: 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");

我有以下代码:

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;
        }
    }
}
package数学;
导入java.io.IOException;
导入java.util.Scanner;
公共班机
{
公共静态void main(字符串[]args)引发IOException
{
println(“嗨,我将击败Java的Math.sqrt(double)方法”);
System.out.println(“两种计算方式都将进行”);
println(“我会计算他们花了多长时间”);
System.out.println(“将生成随机双精度”);
System.out.println();
System.out.println(“请给出将要进行的sqrt计算的数量”);
int calcs=新扫描仪(System.in).nextInt();
布尔输出=真;
如果(计算值>10000)
{
System.out.println(“你要求的计算太多了”);
System.out.println(“建议禁用输出”);
System.out.println(“禁用输出”(y/n)”;
char a=(char)System.in.read();
如果(a='y')
{
输出=假;
}
}
System.out.println(“按回车键开始”);
System.in.read();
测试(计算、输出);
System.out.println();
System.out.println(“我觉得我快多了”);
System.out.println(“现在您可以检查我的精度”);
System.out.println(“请给出一个复杂的双精度”);
double x=double.parseDouble(新扫描仪(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(“现在请做出结论”);
System.out.println(“感谢您的尝试”);
}
公共静态无效测试(整数计算、布尔输出)
{
双因子=Math.random()/2;
//数学
long mathStart=System.currentTimeMillis();

对于(int i=1;i您可能用输出时间压倒了实际的计算时间,并且遇到了缓冲的侥幸。探查器将向您显示实际消耗时间的内容。

Math.sqrt方法遵从StrictMath.sqrt,这是在硬件或本机代码中完成的。(查看JDK的源代码—您将看到它是一个本机方法。)这肯定比你要写的任何东西都要快。它甚至可能使用与你编写的算法相同的算法。这是众所周知的。你的方法只是牛顿计算平方根的方法。这是众所周知的;牛顿只是用微积分重新驱动它。二次收敛很好


无论你做了什么,你都不可能发现任何新的或值得注意的东西。听起来似乎与IO有关的事情是人为地使结果产生偏差。

努力改进现有实现的功劳;即使你失败了,你也可以在这个过程中学到很多关于算法的知识。当然,你必须测试你的备选方案使用这种微基准。不幸的是,存在很多缺陷。尤其是,不要把无关的代码(例如测试和输出)与计算结合起来;在测试早期对JVM进行预热。还有更多。在比较浮点值时,考虑这些。

< P>我不能复制您的结果。尝试了一些T。imes使用EclipseGalileo和JDK1.6.0

对于80000,输出被禁用,我得到如下结果:

Math: 15 milliseconds
I:    32 milliseconds
小时候,最好使用
System.nanoTime()
或更多交互

对于80000,已启用输出:

Math: 3609 milliseconds
I:    4906 milliseconds

因此,问题可能在于处理输出的方式(滚动、缓冲等)

请注意,通常情况下,您会使用从输入的指数派生的更好的起始值。这在实践中非常有用,例如,如果您想计算大整数的近似平方根。您的eclipse控制台设置是什么?无固定宽度,限制:1000000,制表符:8,按标准显示,按标准显示错误,颜色:{应该没有影响}。