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



我看到了很多关于SO的讨论,这些讨论与舍入浮点值有关,但没有可靠的Q&A考虑效率方面。现在是:

将浮点值四舍五入到最接近的整数的最有效(但正确)方法是什么?

(int) (mFloat + 0.5);

Math.round(mFloat);

FloatMath.floor(mFloat + 0.5);

还是别的什么?

最好我想使用标准java库中可用的东西,而不是我必须导入的一些外部库。

基于Q&我想你指的是,各种方法的相对效率取决于你使用的平台

但底线是:

  • 最新的JRE具有针对Math.floor/StrictMath.floor的性能修复,并且
  • 除非你做了大量的四舍五入,否则你用哪种方式做可能不会有任何区别

参考文献:

  • 这是否意味着Java Math.floor非常慢
  • http://bugs.sun.com/view_bug.do?bug_id=6908131("Java.lang.StrictMath.floor(double)和Java.lang.SstrictMath.ceil(double)的纯Java实现")
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));
    }
}

Java SE6:上的输出

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

Java SE7上的输出(感谢alex的结果):

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

正如您所看到的,Math.round从SE6到SE7有了巨大的性能改进。我认为在SE7中已经没有明显的区别了,你应该选择对你来说更可读的。

我应该选择Math.round(mFloat),因为它将舍入逻辑封装在方法中(即使它不是您的方法)。

根据它的文档,您编写的代码与Math.round执行的代码相同(除了检查边界情况)。

无论如何,更重要的是算法的时间复杂性,而不是像小常数这样的事情的时间。。。除了你正在编程的东西会被调用数百万次!:D

编辑:我不知道FloatMath。它来自JDK吗?

您可以使用System.currentTimeMillis()对其进行基准测试。您将看到差异太小

对于负数,简单地加0.5会得到不正确的结果。请参阅Math.round的更快实现?以获得更好的解决方案。

相关内容

  • 没有找到相关文章

最新更新