【问题标题】:What's more efficient/ cheaper, casting or a method call?什么更有效/更便宜,铸造或方法调用?
【发布时间】:2012-08-04 23:02:57
【问题描述】:

我有一个Double,在转换为String 之前,我想去掉小数点后的多余数字(我不太关心准确性,但可以在您的回答中随意提及) .

我想知道是转换为 int 还是使用 DecimalFormat 并调用 format(..) 会更好。此外,指定String.valueOf() 还是保持原样并让编译器弄清楚是否更有效?

对不起,如果我听起来有点无知,我真的很想了解更多技术细节。

作为参考,我正在将文本绘制到 android 画布:

c.drawText("FPS: " + String.valueOf((int)lastFps), xPos, yPos, paint); 

【问题讨论】:

  • 创建一个循环,执行这一百万次并比较结果

标签: java performance casting type-conversion


【解决方案1】:

铸造可能会更有效。这是作为本机代码实现的,而使用方法必须通过 java 代码。它也更具可读性。

对于 string.valueof,我希望性能完全相同。我发现 "string" + intValue"string" + String.valueof(intValue) 更具可读性

【讨论】:

    【解决方案2】:

    我做了一个程序,使用 System.nanoTime() 来计算这两种方法的执行时间:

        public static void cast() {
        for (int i=0; i<1000000; i++) {
            int x= (int)Math.random();
        }
    }
    
    public static void format() {
        for (int i=0; i< 1000000; i++) {
            DecimalFormat df = new DecimalFormat("#");
            df.format(Math.random());
        }
    }
    

    以下是各自的结果:

    80984944

    6048075593

    我的测试可能不是完美的例子。我只是在使用 math.random(),它会生成一个始终强制转换为 0 的数字,这可能会影响结果。然而,这些结果确实有意义——强制转换应该很便宜,因为它可能根本不对位进行操作——JVM 只是以不同的方式处理这些位。

    编辑:如果我为第二个示例提取格式化程序的实例化,程序将在 3155165182ns 中运行。如果我在这两种情况下都将随机数乘以 Integer.MAX_VALUE(取出实例化),结果是:82100170 和 4174558079。看起来强制转换是要走的路。

    【讨论】:

    • 此外,如果十进制格式始终相同,您可以通过将实例化从 for 循环中拉出来获得更准确的读数。
    • 将随机结果乘以 Integer.MAX_VALUE 这样的大数,然后你会有一个更公平的比较
    • 提取实例化的优点。我的推理是问题是“哪个过程更快”,并且由于实例化对于该过程是必要的,因此我将其包括在内。但是,由于它始终是相同的格式化程序,并且优化只有在您重复多次时才真正重要,因此将其拉出是有意义的。执行此操作时,程序运行时间为 3155165182 纳秒 - 仍然远远落后于强制转换。
    • 感谢所有答案,但您和 MattiasSp 都花时间进行了一些测试,您首先回答了。我真的应该自己运行它们,但我认为这可能是常识:p欢呼
    【解决方案3】:

    这是Math.floor().的工作

    【讨论】:

      【解决方案4】:

      一般来说,函数/方法调用是以性能开销为代价的。我的投票是类型转换会更快,但正如@Zefiryn 建议的那样,最好的方法是创建一个循环并多次执行每个操作并使用计时器测量性能。

      【讨论】:

        【解决方案5】:

        我不确定两者的效率,但这里有第三种比较有趣的选项:

        String.valueOf(doubleValue).substring(0, endInt)
        

        这将给出一组字符而不是小数/数字,并且会跳过类型转换而是进行两个函数调用。

        编辑:太好奇了,所以我尝试运行每个选项:

        integerNumberFormat.format(number)
        String.valueOf(doubleValue).substring(0, endInt)
        String.valueOf((int)doubleValue)
        

        10^6 个周期,结果分别为 ~800 ms、~300 ms 和 ~40 ms。我想我的结果不会立即转化为您的情况,但它们可以暗示最后一个确实是,正如之前的海报所暗示的那样,最快的一个。

        【讨论】:

        • 非常感谢您抽出宝贵时间进行测试!子字符串的使用也是一种有趣的方法!
        猜你喜欢
        • 1970-01-01
        • 2013-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-09
        • 1970-01-01
        相关资源
        最近更新 更多