简体   繁体   English

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

[英](int) Math.sqrt(n) much slower than (int) Math.floor(Math.sqrt(n))

I was looking at my code, hoping to improve its performance and then i saw this: 我正在查看我的代码,希望提高其性能,然后我看到了这个:

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

Oh, ok, i don't really need the call to Math.floor, as casting the double returned from Math.sqrt(n) will be effectively flooring the number too (as sqrt will never return a negative number). 哦,好吧,我真的不需要调用Math.floor,因为从Math.sqrt(n)返回的强制转换也会有效地对数字进行拼接(因为sqrt永远不会返回负数)。 So i went and dropped the call to Math.floor: 所以我去了Math.floor的电话:

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

sat back and complacently watched the code run and perform roughly 10% ! 坐下来,自满地看着代码运行并执行大约10%! worse than its previous version. 比以前的版本更糟糕。 This came to me as a shock. 这令我感到震惊。 Any ideas anyone? 任何人的想法?

Math.floor javadocs: "Returns the largest (closest to positive infinity) double value that is less than or equal to the argument and is equal to a mathematical integer." Math.floor javadocs:“返回小于或等于参数且等于数学整数的最大(最接近正无穷大)double值。”

EDIT in my case n is a long. 在我的情况下编辑 n很长。 Any chance cast-floor-sqrt would ever produce a different int than cast-sqrt? 任何机会cast-floor-sqrt都会生成与cast-sqrt不同的int? I personally can't see why it ever would... all numbers involved are positive. 我个人不明白为什么会这样......所有涉及的数字都是积极的。

The Math.floor method just delegates the call to the StrictMath.floor method (see here ). Math.floor方法只是将调用委托给StrictMath.floor方法(参见此处 )。 This method is a native method. 此方法是本机方法。 After this method the cast does not have to do anything because it is already a number that is equal to an integer (so no decimal places). 在此方法之后,强制转换不必执行任何操作,因为它已经是一个等于整数的数字(因此没有小数位)。

Maybe the native implementation of floor is faster than the cast of a double value to an int value. 也许底层的本机实现比将int值转换为double值更快。

I cannot reproduce the same results. 我无法重现相同的结果。 Using this simple Java code below, the function without the call to Math.floor is consistently faster: 使用下面这个简单的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();
    }
}

Also, looking at the disassembled byte code we can clearly see the call to Math.floor in the first function and no call in the second. 另外,查看反汇编的字节代码,我们可以清楚地看到第一个函数中对Math.floor的调用,第二个函数中没有调用。 There must be something else going on in your code. 您的代码中必定还有其他内容。 Perhaps you can post your code or a shortened version of it that shows the results that you are seeing. 也许您可以发布您的代码或缩短版本,以显示您所看到的结果。

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        

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM