为什么在Java中浮动似乎添加不正确?

为什么在Java中浮动似乎添加不正确?,java,math,Java,Math,可能的重复项: 我有最新的密码 for(double j = .01; j <= .17; j+=.01){ System.out.println(j); } 有人能解释为什么会这样吗?你怎么解决这个问题?除了编写舍入函数之外?它们工作正常。有些十进制值不能用二进制浮点精确表示,因此会四舍五入到最接近的值。有关更多详细信息,请参见我对的回答。有人问了关于Perl的问题,但答案同样适用于Java,因为它限制了所有不具有无限精度的浮点表示法,即所有浮

可能的重复项:

我有最新的密码

for(double j = .01; j <= .17; j+=.01){
            System.out.println(j);
        }

有人能解释为什么会这样吗?你怎么解决这个问题?除了编写舍入函数之外?

它们工作正常。有些十进制值不能用二进制浮点精确表示,因此会四舍五入到最接近的值。有关更多详细信息,请参见我对的回答。有人问了关于Perl的问题,但答案同样适用于Java,因为它限制了所有不具有无限精度的浮点表示法,即所有浮点表示法。

由于它们的存储方式,浮点表示法是Java中实际数的近似值。如果您需要精确的值,请改用。

在计算机上使用双精度表示是正常的。你失去了一些,那么你就会有这样的结果。更好的解决方案是这样做:

for(int j = 1; j <= 17; j++){
    System.out.println(j/100.0);
}

这是因为浮点值本质上与数学意义上的实数不同


在计算机中,只有固定数量的位可以用来表示值。这意味着它可以保存有限数量的值。但实数的数量是无限的,因此并非所有的实数都可以精确地表示。但通常情况下,价值是接近的。你可以找到更详细的解释

正如@Kaleb Brasee所建议的,在必须准确的情况下,使用BigDecimal's。下面是一个链接,它很好地解释了在Java中使用浮点操作的一些细节

还有一个链接指向与使用BigDecimal有关的问题。强烈建议同时阅读这两本书。它真的帮助了我。
享受吧,波罗。

这是因为二进制格式的局限性,无法最大限度地利用32位。

当我们“手工”处理浮点数时,我们人类习惯于以“10为基数”思考,也就是说,在纸上写浮点数或将浮点数输入计算机时。正因为如此,我们有可能写下准确的代表性,比如说,17%。我们只写了0.17或1.7E-1等等,试图用这个系统来表示第三个这样的小事是不可能的,因为我们必须写0.3333。。。有无限多的3,这是不可能的

处理浮点运算的计算机不仅具有有限的位数来表示数字的尾数或有效位,而且还被限制在以二为底来表示尾数。这意味着,我们人类使用基数为10的浮点约定,可以准确写入的大多数百分比,例如“0.17”,计算机不可能准确存储。像0%、25%、50%、75%和100%这样的分数可以在计算机中精确地表示为浮点数,因为它由两半2E-1或四分之一2E-4组成,与数字表示非常吻合。对于我们人类来说,百分之十七甚至微不足道的数值!!对于计算机来说,10%或1%是不可能精确存储的,因为这些数字对于二进制浮点系统来说,就像对于人类基数为10的浮点系统来说,“三分之一”一样

但是如果你仔细挑选你的浮点值,那么它们总是由一个1/2^n的整数组成,其中n可能是10,意味着一个1/1024的整数,那么它们总是可以作为一个浮点数准确地存储而没有错误。因此,如果你尝试在计算机中存储17/1024,它将顺利进行。实际上,即使使用“human base 10”十进制系统,您也可以毫无错误地存储它,但您必须处理的实际数字数量会让您发疯


我相信这就是为什么有些游戏以一个单位表示角度,而整个360度旋转是256个角度单位。可以毫无损失地表示为0到1之间的浮点数,其中1表示完全旋转。

正如其他人所指出的,只有二次幂的组合数字才能以二元浮点格式精确表示

如果需要以任意精度存储任意数字,请使用BigDecimal

如果问题只是一个显示问题,那么您可以通过如何显示数字来解决这个问题。例如:

字符串格式%.2f,n


将数字的格式设置为小数点后2位。

请参阅相关内容:@JW:这是一个非常有用的链接,因为它回答了大量类似的问题,而且内容完整、正确,而且简短易读。非常感谢。@matt:我希望人们不要再贴那个链接了。这不是一个很好的参考资料,除非你想读一本小书来了解浮点数是如何工作的,否则它真的没有那么复杂@BlueRaja我不同意,我认为这是一个很好的参考,表明浮点数学是一个非常复杂的野兽,它比将十进制数相加要复杂得多。一般的答案是正确的,但关于角度的注释通常是错误的。在所有三角函数c中 按照游戏进行计算。。您将结束使用double和sin/cos函数,从ASCII表示取整到float/double对游戏没有影响:0.0001辐射误差对2D或3D中的绘图场景没有影响。。。
for(int j = 1; j <= 17; j++){
    System.out.println(j/100.0);
}