Java:性能 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");
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 次计算并启用输出,我的方法会快得多。
有人可以解释一下吗?
谢谢
抱歉英语不好。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我无法重现你的结果。使用 Eclipse Galileo 和 JDK 1.6.0 尝试过几次。
对于 80000,禁用输出,我得到类似:
小时间,最好使用 System.nanoTime() 或更多交互。
对于 80000,启用输出:
所以问题可能是处理输出的方式(滚动、缓冲……)
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:
small times, It would be better to use
System.nanoTime()
or more interactions.For 80000, output enabled:
So probably the problem is the way that output is handled (scrolling, buffering, ...)
Math.sqrt 方法遵循 StrictMath.sqrt,它是在硬件或本机代码中完成的。 (查看 JDK 的源代码 - 您会发现它是本机方法。)这肯定比您编写的任何内容都要快。它甚至可能使用与您编码相同的算法。这是众所周知的。您的方法只是计算平方根的牛顿法。 自巴比伦以来就已为人所知;牛顿只是用微积分重新推导了它。二次收敛性良好。
无论您做了什么,您都不太可能发现任何新的或值得注意的东西。听起来好像与 IO 有关的事情人为地使结果产生偏差。
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.
您可能会用输出时间压倒实际计算时间,并遇到缓冲的侥幸。分析器会向您显示实际消耗时间的内容。
You're probably overwhelming the actual calculation time with the output time, and running into a fluke of the buffering. A profiler would show you what's actually consuming the time.
感谢您尝试改进现有的实现;即使你失败了,你也可以在这个过程中学到很多关于算法的知识。当然,您必须使用这种微基准测试您的替代方案。不幸的是,有很多陷阱。特别是,不要将不相关的代码(例如测试和输出)与您的计算混合在一起; 请在测试早期预热 JVM。这篇有关基准测试的文章中有更多内容。另外,在比较浮点值时,请考虑这些比较浮点数的指南< /a>.
Kudos for trying to improve on an existing implementation; even if you fail, you can learn a lot about algorithms in the process. Naturally, you have to test your alternative using this kind of micro-benchmark. Unfortunately, there are numerous pitfalls. In particular, don't mix irrelevant code, e.g testing and output, with your calculation; do warm up the JVM early in your test. There's more in this article on bechmarking. Also, when comparing floating point values, consider these Guidelines for comparing floating point numbers.