简体   繁体   English

将浮点值舍入到java中最接近的整数的最有效方法是什么?

[英]What is the most efficient way to round a float value to the nearest integer in java?

I've seen a lot of discussion on SO related to rounding float values, but no solid Q&A considering the efficiency aspect. 我已经看到很多关于SO与舍入浮点值有关的讨论,但没有考虑效率方面的可靠问答。 So here it is: 所以这里是:

What is the most efficient (but correct) way to round a float value to the nearest integer? 将浮点值舍入到最接近的整数的最有效(但正确)方法是什么?

(int) (mFloat + 0.5);

or 要么

Math.round(mFloat);

or 要么

FloatMath.floor(mFloat + 0.5);

or something else? 或者是其他东西?

Preferably I would like to use something available in standard java libraries, not some external library that I have to import. 我最好使用标准java库中可用的东西,而不是我必须导入的一些外部库。

Based on the Q&A's that I think you are referring to, the relative efficiency of the various methods depends on the platform you are using . 基于我认为您所指的Q&A,各种方法的相对效率取决于您使用的平台

But the bottom line is that: 但底线是:

  • the latest JREs have the performance fix for Math.floor / StrictMath.floor , and 最新的JRE具有Math.floor / StrictMath.floor的性能修复,以及
  • unless you are doing an awful lot of rounding, it probably doesn't make any difference which way you do it. 除非你做了很多的四舍五入,否则你可能没有任何区别。

References: 参考文献:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            measurementIteration();
        }
    }

    public static void measurementIteration() {
        long s, t1 = 0, t2 = 0;
        float mFloat = 3.3f;
        int f, n1 = 0, n2 = 0;
        for (int i = 0; i < 1E4; i++) {
            switch ((int) (Math.random() * 2)) {
            case 0:
                n1 += 1E4;
                s = System.currentTimeMillis();
                for (int k = 0; k < 1E4; k++)
                    f = (int) (mFloat + 0.5);
                t1 += System.currentTimeMillis() - s;
                break;
            case 1:
                n2 += 1E4;
                s = System.currentTimeMillis();
                for (int k = 0; k < 1E4; k++)
                    f = Math.round(mFloat);
                t2 += System.currentTimeMillis() - s;
                break;
            }
        }
        System.out.println(String.format("(int) (mFloat + 0.5): n1 = %d    -> %.3fms/1000", n1, t1 * 1000.0 / n1));
        System.out.println(String.format("Math.round(mFloat)  : n2 = %d    -> %.3fms/1000", n2, t2 * 1000.0 / n2));
    }
}

Output on Java SE6: Java SE6上的输出:

(int) (mFloat + 0.5): n1 = 500410000    -> 0.003ms/1000
Math.round(mFloat)  : n2 = 499590000    -> 0.022ms/1000

Output on Java SE7 (thanks to alex for the results): Java SE7上的输出(感谢alex的结果):

(int) (mFloat + 0.5): n1 = 50120000 -> 0,002ms/1000
Math.round(mFloat) : n2 = 49880000 -> 0,002ms/1000

As you can see, there was a huge performance improvement on Math.round from SE6 to SE7. 正如您所看到的,从SE6到SE7, Math.round性能有了很大的提升。 I think in SE7 there is no significant difference anymore and you should choose whatever seems more readable to you. 我认为在SE7中不再存在显着差异,你应该选择对你来说更具可读性的东西。

I should go for Math.round(mFloat) cause it's encapsuling rounding logic in a method (even if it's not your method). 我应该去Math.round(mFloat)因为它在方法中封装了舍入逻辑(即使它不是你的方法)。

According with its documentation the code you've written is the same that Math.round executes (except it checks border cases). 根据其文档 ,您编写的代码与Math.round执行的代码相同(除了检查边界情况)。

Anyway what is more important is the time-complexity of your algorithm, not the time for small constant-like things... Except you are programming something that will be invoked millions of times! 无论如何,更重要的是算法的时间复杂性,而不是小型常数事物的时间......除非你编程的东西会被调用数百万次! :D :d

Edit: I don't know FloatMath. 编辑:我不知道FloatMath。 Is it from JDK? 它来自JDK吗?

You may benchmark it by using System.currentTimeMillis() . 您可以使用System.currentTimeMillis()对其进行基准测试。 You will see that difference is too little 你会发现差异太小了

Simply adding 0.5 will give an incorrect result for negative numbers. 简单地添加0.5将给出负数的错误结果。 See Faster implementation of Math.round? 请参阅更快的Math.round实现? for a better solution. 为了更好的解决方案。

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

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