在表示整数的浮点数中是否也会出现舍入错误?

时间:2015-01-16 17:43:17

标签: java rounding rounding-error

按如下方式创建一系列数字时,

    float increment = 0.01f;
    for (int i = 0; i < 100; i++) {
        float value = i * increment;
        System.out.println(value);
    }
很明显,我会以一些像我这样的价值观结束 0.049999997,由于舍入误差,它们不是0.01的精确倍数。

当我尝试使用通常整数范围内的浮点数时,我从未见过同样的问题:

float increment = 1.0f; //Still a float but representing an int value
for (int i = 0; i < 100; i++) {
    float value = i * increment;
    System.out.println(value);
}

可以预料到,这也打印出来,例如: 49.999999而不是50,但我从未见过。

我想知道,我是否可以依赖于i的任何值和任何增量值,只要它表示一个整数(尽管它的类型是浮点数)。

如果是这样,我会对解释感兴趣,为什么在这种情况下不能进行舍入错误。

3 个答案:

答案 0 :(得分:2)

某个范围内的整数(大约一百万左右)可以完全表示为浮点数。因此,当您只使用它们时,不会出现舍入错误。

答案 1 :(得分:0)

它并不真正代表整数。它仍然是一个浮动,你只是试图将值1.0添加到。一旦1.0下溢(每当指数大于零时),你就会得到四舍五入的错误。

答案 2 :(得分:0)

这是因为float基于浮点表示法。

粗话说,它试图将你的十进制数表示为权力分数的总和2.

这意味着它会尝试将1/2 ^ n1 + 1/2 ^ n2 + 1/2 ^ n3 .... 1/2 ^ nm加起来直到得到关闭或你输入的确切值。

例如(粗鲁):
0.5它将表示为1/2
0.25表示为1 /2²
0.1它将表示为1/2 ^ 4
但在这种情况下,它会将数字多少1.600000023841858(尾数),它会给出一个更接近但不等于1的数字(1/2 ^ 4 x 1.600000023841858 = 0,100000001

现在你可以看到为什么在一些循环后,值变为无意义值

有关其工作原理的详细信息,请阅读浮点IEEE 754

如果你想要精度,你应该使用例如Java中的BigDecimal,它使用另一种架构来表示十进制数。

Double有同样的问题。

选中此工具以查看浮点的重现: http://www.h-schmidt.net/FloatConverter/IEEE754.html