我正在查看我的代码,希望提高其性能,然后我看到了:
int sqrt = (int) Math.floor(Math.sqrt(n));
哦,好吧,我真的不需要调用Math.floor,因为从Math.sqrt(n)返回的强制转换也会有效地对数字进行拼接(因为sqrt永远不会返回负数)。所以我去了Math.floor:
int sqrt = (int) Math.sqrt(n)
坐下来,自满地看着代码运行并执行大约10%!比以前的版本更糟糕。这令我感到震惊。任何人的想法?
Math.floor javadocs:“返回小于或等于参数的最大(最接近正无穷大)double值,并且等于数学整数。”
修改 就我而言, n 很长。任何机会cast-floor-sqrt都会生成与cast-sqrt不同的int?我个人无法理解为什么会这样......所有涉及的数字都是积极的。
答案 0 :(得分:6)
Math.floor方法只是将调用委托给StrictMath.floor方法(参见here)。此方法是本机方法。在此方法之后,强制转换不必执行任何操作,因为它已经是一个等于整数的数字(因此没有小数位)。
也许本地实现floor比使用double值转换为int值更快。
答案 1 :(得分:1)
我无法重现相同的结果。使用下面这个简单的Java代码,没有调用Math.floor的函数一直更快:
with floor elapsed milliseconds: 7354
without floor elapsed milliseconds: 4252
public class TestCast {
private static final int REPS = Integer.MAX_VALUE / 4;
private static void withFloor() {
long sum = 0;
long start = System.currentTimeMillis();
for (int i = REPS; i != 0; --i) {
sum += (int)Math.floor(Math.sqrt(i));
}
long end = System.currentTimeMillis();
long elapsed = end - start;
System.out.println("with floor elapsed milliseconds: " + elapsed);
System.out.println(sum);
}
private static void withoutFloor() {
long sum = 0;
long start = System.currentTimeMillis();
for (int i = REPS; i != 0; --i) {
sum += (int)Math.sqrt(i);
}
long end = System.currentTimeMillis();
long elapsed = end - start;
System.out.println("without floor elapsed milliseconds: " + elapsed);
System.out.println(sum);
}
public static void main(String[] args) {
withFloor();
withoutFloor();
}
}
另外,查看反汇编的字节代码,我们可以清楚地看到第一个函数中对Math.floor的调用,第二个函数中没有调用。您的代码中必定还有其他内容。也许您可以发布您的代码或缩短版本,以显示您所看到的结果。
private static void withFloor();
Code:
0: lconst_0
1: lstore_0
2: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
5: lstore_2
6: ldc #3 // int 536870911
8: istore 4
10: iload 4
12: ifeq 35
15: lload_0
16: iload 4
18: i2d
19: invokestatic #4 // Method java/lang/Math.sqrt:(D)D
22: invokestatic #5 // Method java/lang/Math.floor:(D)D
25: d2i
26: i2l
27: ladd
28: lstore_0
29: iinc 4, -1
32: goto 10
35: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
38: lstore 4
40: lload 4
42: lload_2
43: lsub
44: lstore 6
46: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
49: new #7 // class java/lang/StringBuilder
52: dup
53: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
56: ldc #9 // String with floor elapsed milliseconds:
58: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
61: lload 6
63: invokevirtual #11 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
66: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
69: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
72: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
75: lload_0
76: invokevirtual #14 // Method java/io/PrintStream.println:(J)V
79: return
private static void withoutFloor();
Code:
0: lconst_0
1: lstore_0
2: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
5: lstore_2
6: ldc #3 // int 536870911
8: istore 4
10: iload 4
12: ifeq 32
15: lload_0
16: iload 4
18: i2d
19: invokestatic #4 // Method java/lang/Math.sqrt:(D)D
22: d2i
23: i2l
24: ladd
25: lstore_0
26: iinc 4, -1
29: goto 10
32: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
35: lstore 4
37: lload 4
39: lload_2
40: lsub
41: lstore 6
43: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
46: new #7 // class java/lang/StringBuilder
49: dup
50: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
53: ldc #15 // String without floor elapsed milliseconds:
55: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
58: lload 6
60: invokevirtual #11 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
63: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
66: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
69: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
72: lload_0
73: invokevirtual #14 // Method java/io/PrintStream.println:(J)V
76: return