Java (int) Math.sqrt(n) 比 (int) Math.floor(Math.sqrt(n)) 慢得多

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20265468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:41:42  来源:igfitidea点击:

(int) Math.sqrt(n) much slower than (int) Math.floor(Math.sqrt(n))

javaperformancecastingfloor

提问by Peter Perhá?

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). So i went and dropped the call to Math.floor:

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

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

sat back and complacently watched the code run and perform roughly 10% ! worse than its previous version. This came to me as a shock. Any ideas anyone?

坐下来自满地看着代码运行并执行大约 10% !比之前的版本差。这让我感到震惊。任何人的想法?

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:“返回小于或等于参数且等于数学整数的最大(最接近正无穷大)双精度值。”

EDITin my case nis a long. Any chance cast-floor-sqrt would ever produce a different int than cast-sqrt? I personally can't see why it ever would... all numbers involved are positive.

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

采纳答案by mvieghofer

The Math.floor method just delegates the call to the StrictMath.floor method (see here). 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).

Math.floor 方法只是将调用委托给 StrictMath.floor 方法(参见此处)。此方法是本机方法。在这个方法之后,转换不需要做任何事情,因为它已经是一个等于整数的数字(所以没有小数位)。

Maybe the native implementation of floor is faster than the cast of a double value to an int value.

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

回答by Barzee

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. 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.

此外,查看反汇编的字节码,我们可以清楚地看到第一个函数中对 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