我想知道以下哪一项会更好地执行,只是出于好奇。语言是Java。
int num = -500;
int num2 = 0;
while( Math.abs(num) > num2 )
num2 ++;
或
int num = -500;
int num2 = 0;
num = Math.abs(num);
while( num > num2 )
num2 ++;
基本上我想知道' Math.abs'是为while循环的每次迭代调用,还是在后台进行一些代码优化?
谢谢!
答案 0 :(得分:5)
Math.abs()
就是所谓的pure function,所以一个非常好的编译器理论上可以优化它。有专门设计的函数式编程语言可以做到这一点,但在Java中很难。
第二个不仅可以编译成更快的代码,它通常被认为是更好的风格,因为它更清楚地说明了循环中实际变化的内容以及没有变化的内容。
答案 1 :(得分:3)
是的,每次迭代都会调用Math.abs(num)
,因为Java永远不会告诉或猜测返回值仅取决于参数。
对于Java,该方法与Math.random()
“相等”。
所以第一个例子使用了更多的CPU时间。
答案 2 :(得分:1)
出于好奇,我执行了一个不科学的基准测试,返回了以下结果:
为了可比性:
主机信息:
答案 3 :(得分:0)
第二个必须在while循环的每次传递中执行绝对值函数。当然,只有当Java不再优化存储这样的操作结果时才会出现这种情况,我相信情况就是如此。 Java暂时还没有优化,它现在依赖于JIT。
所以回答你的问题,第一个更快。
答案 4 :(得分:0)
Java代码
package test;
public class SpeedTest
{
public void first()
{
int num = -500;
int num2 = 0;
while( Math.abs(num) > num2 )
num2 ++;
}
public void second()
{
int num = -500;
int num2 = 0;
num = Math.abs(num);
while( num > num2 )
num2 ++;
}
}
字节代码
Compiled from "SpeedTest.java"
public class test.SpeedTest extends java.lang.Object{
public test.SpeedTest();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public void first();
Code:
0: sipush -500
3: istore_1
4: iconst_0
5: istore_2
6: goto 12
9: iinc 2, 1
12: iload_1
13: invokestatic #15; //Method java/lang/Math.abs:(I)I
16: iload_2
17: if_icmpgt 9
20: return
public void second();
Code:
0: sipush -500
3: istore_1
4: iconst_0
5: istore_2
6: iload_1
7: invokestatic #15; //Method java/lang/Math.abs:(I)I
10: istore_1
11: goto 17
14: iinc 2, 1
17: iload_1
18: iload_2
19: if_icmpgt 14
22: return
}
从上面两者基本上都是〜20指令。如果你非常挑剔,那么第一个很快。
区别的原因是您正在计算并将结果存储在第二种方法中。您需要在比较时再次弹出。在第一种情况下,您直接比较Math.abs
之后的寄存器值。并且因此两个额外的指令。
As pointed out by @ide and @bestsss:
中的指令数量 字节码并不真正与之相关 他们实际上的次数 调用。还有HotSpot来加香料 事情进一步发展(如死代码 优化)。
在此示例中,Math.abs()
在固定值-500时调用。因此,HotSpot JVM可以对其进行优化。
有关详细信息,请参阅以下注释。
答案 5 :(得分:0)
class AbsTest {
public static void main(String[] args) {
int num = -2000000000;
int num2 = 0;
long then = System.currentTimeMillis();
while( Math.abs(num) > num2 )
num2 ++;
long then2 = System.currentTimeMillis();
num = Math.abs(num);
num2 = 0;
while( num > num2 )
num2 ++;
long now = System.currentTimeMillis();
System.out.println(then2 - then); // first time
System.out.println(now - then2); // second time
}
}
结果:
C:\Documents and Settings\glowcoder\My Documents>java AbsTest
2953
1828
C:\Documents and Settings\glowcoder\My Documents>
答案 6 :(得分:0)
Hey Inventor我认为将这两者进行比较是没有价值的,因为它取决于您的编译器实现。正如
如果您的编译器执行优化,那么您发现两个代码很可能会占用相同的运行时间。
如果它没有执行那么显然第二个更快。
所以我认为你不应该担心这些事情。