6

我正在查看我的代码,希望提高它的性能,然后我看到了这个:

int sqrt = (int) Math.floor(Math.sqrt(n));

哦,好吧,我真的不需要对 Math.floor 的调用,因为从 Math.sqrt(n) 返回的 double 类型也将有效地对数字进行求底(因为 sqrt 永远不会返回负数)。所以我去挂断了对 Math.floor 的电话:

int sqrt = (int) Math.sqrt(n)

坐下来,自满地看着代码运行并执行大约 10%!比以前的版本差。这让我感到震惊。有什么想法吗?

Math.floor javadocs:“返回小于或等于参数且等于数学整数的最大(最接近正无穷大)双精度值。”

在我的情况下,编辑n很长。任何机会 cast-floor-sqrt 会产生与 cast-sqrt 不同的 int 吗?我个人看不出它为什么会……所有涉及的数字都是正数。

4

2 回答 2

6

Math.floor方法只是将调用委托给该StrictMath.floor方法(如 java.lang.StrictMath的源代码所示)。此方法是本机方法。在这个方法之后,演员不必做任何事情,因为它已经是一个等于整数的数字(所以没有小数位)。

也许 floor 的本机实现比将 double 值转换为 int 值更快。

于 2013-11-28T12:05:15.683 回答
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        
于 2013-11-28T19:30:30.120 回答