(int)Math.sqrt(n)比(int)Math.floor(Math.sqrt(n))慢很多

时间:2013-11-28 11:51:26

标签: java performance casting floor

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

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?我个人无法理解为什么会这样......所有涉及的数字都是积极的。

2 个答案:

答案 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