我有这段代码:
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;
}
}
}
此sqrt方法称为“ heroon ” 如果我运行我的程序并且我要求80000计算并禁用输出,Math.sqrt()比我的方法快得多。如果我询问80000计算并启用输出,我的方法要快得多。
有人可以解释一下吗?
由于
抱歉英语不好。
答案 0 :(得分:5)
Math.sqrt方法遵循StrictMath.sqrt,它以硬件或本机代码完成。 (查看JDK的源代码 - 您将看到它是一种本机方法。)这肯定比您编写的任何内容都要快。它甚至可能使用您编码的相同算法。众所周知。你的方法只是牛顿计算平方根的方法。众所周知since Babylon;牛顿只是使用微积分重新获得它。二次收敛是好的。
无论你做了什么,你都不可能发现任何新的或值得注意的东西。听起来像与IO有关的事情是人为地偏向结果。
答案 1 :(得分:5)
我无法重现您的结果。使用Eclipse Galileo和JDK 1.6.0尝试了一些时间。
对于80000,输出已禁用,我有类似的内容:
Math: 15 milliseconds
I: 32 milliseconds
很少一段时间,最好使用System.nanoTime()
或更多互动。
对于80000,启用输出:
Math: 3609 milliseconds
I: 4906 milliseconds
所以可能问题是处理输出的方式(滚动,缓冲......)
答案 2 :(得分:3)
你可能用输出时间压倒了实际的计算时间,并且遇到了缓冲的侥幸。分析器会向您显示实际消耗时间的内容。
答案 3 :(得分:3)
鼓励尝试改进现有的实施;即使你失败了,你也可以在这个过程中学到很多关于算法的知识。当然,您必须使用这种微基准测试您的替代方案。不幸的是,有很多陷阱。特别是,不会将不相关的代码(例如测试和输出)与您的计算混合在一起; 做在测试的早期预热JVM。这个article on bechmarking还有更多内容。此外,在比较浮点值时,请考虑这些Guidelines for comparing floating point numbers。