当前位置:  开发笔记 > 编程语言 > 正文

为什么计数到2 ^ 24会很快执行,但计算到2 ^ 25需要更长的时间?

如何解决《为什么计数到2^24会很快执行,但计算到2^25需要更长的时间?》经验,为你挑选了1个好方法。

我正在摆弄无限循环来测试其他代码/我的理解,并遇到了这种奇怪的行为.在下面的程序中,从0到2 ^ 24的计数在我的机器上花费<100ms,但是计数到2 ^ 25需要更多的时间(在写入时,它仍在执行).

为什么会这样?

这是在Windows 1.8的64位副本上的Java 1.8.0_101下.

TestClass.java

public class TestClass {
    public static void main(String[] args) {
        addFloats((float) Math.pow(2.0, 24.0));
        addFloats((float) Math.pow(2.0, 25.0));
    }

    private static void addFloats(float number) {
        float f = 0.0f;
        long startTime = System.currentTimeMillis();

        while(true) {
            f += 1.0f;
            if (f >= number) {
                System.out.println(f);
                System.out.println(number + " took " + (System.currentTimeMillis() - startTime) + " msecs");
                break;
            }
        }
    }
}

resueman.. 16

这是因为floats具有可以表示的最小精度,随着floats值变大而减小.在2 ^ 24和2 ^ 25之间,添加一个不再足以将值更改为下一个最大可表示数字.此时,每次循环时,f只保持相同的值,因为f += 1.0f不再更改它.

如果您将循环更改为:

while(true) {
    float newF = f + 1.0f;
    if(newF == f) System.out.println(newF);
    f += 1.0f;
    if (f >= number) {
        System.out.println(f);
        System.out.println(number + " took " + (System.currentTimeMillis() - startTime) + " msecs");
        break;
    }
}

你可以看到这种情况发生.似乎它一旦f达到2 ^ 24 就停止增加.

如果你用2 ^ 25运行它,上面代码的输出将是无穷无尽的"1.6777216E7".

您可以使用该Math.nextAfter函数测试此值,该函数告诉您下一个可表示的值.如果您尝试运行此代码:

float value = (float)Math.pow(2.0, 24.0);
System.out.println(Math.nextAfter(value, Float.MAX_VALUE) - value);

你可以看到2 ^ 24之后的下一个可表示的值是2 ^ 24 + 2.

为了更好地解释为什么会发生这种情况,以及为什么它开始在何处发生,请参阅此答案



1> resueman..:

这是因为floats具有可以表示的最小精度,随着floats值变大而减小.在2 ^ 24和2 ^ 25之间,添加一个不再足以将值更改为下一个最大可表示数字.此时,每次循环时,f只保持相同的值,因为f += 1.0f不再更改它.

如果您将循环更改为:

while(true) {
    float newF = f + 1.0f;
    if(newF == f) System.out.println(newF);
    f += 1.0f;
    if (f >= number) {
        System.out.println(f);
        System.out.println(number + " took " + (System.currentTimeMillis() - startTime) + " msecs");
        break;
    }
}

你可以看到这种情况发生.似乎它一旦f达到2 ^ 24 就停止增加.

如果你用2 ^ 25运行它,上面代码的输出将是无穷无尽的"1.6777216E7".

您可以使用该Math.nextAfter函数测试此值,该函数告诉您下一个可表示的值.如果您尝试运行此代码:

float value = (float)Math.pow(2.0, 24.0);
System.out.println(Math.nextAfter(value, Float.MAX_VALUE) - value);

你可以看到2 ^ 24之后的下一个可表示的值是2 ^ 24 + 2.

为了更好地解释为什么会发生这种情况,以及为什么它开始在何处发生,请参阅此答案


换句话说,第二个不仅需要更长的时间 - 它是一个无限循环!
推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有