为什么浮点数似乎在Java中添加错误?

时间:2011-04-08 19:29:59

标签: java math

  

可能重复:
  Is JavaScript's Math broken?
  Java floating point arithmetic

我有当前的代码

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

输出是:

0.01
0.02
0.03
0.04
0.05
0.060000000000000005
0.07
0.08
0.09
0.09999999999999999
0.10999999999999999
0.11999999999999998
0.12999999999999998
0.13999999999999999
0.15
0.16
0.17

有人可以解释为什么会这样吗?你是如何解决这个问题的?除了写一个舍入函数?

8 个答案:

答案 0 :(得分:5)

Floats是Java中实际数字的近似值,因为它们的存储方式。如果您需要确切的值,请改用BigDecimal

答案 1 :(得分:2)

他们正常工作。某些十进制值无法在二进制浮点中精确表示,并四舍五入到最接近的值。有关详细信息,请参阅我对this question的回答。问题是关于Perl的问题,但答案同样适用于Java,因为它是所有浮点表示的限制,它们没有无限精度(即所有浮点数)。

答案 2 :(得分:1)

正如@Kaleb Brasee所建议的那样,当准确性是必须时,请使用BigDecimal。这里有一个链接,可以很好地解释与在Java http://firstclassthoughts.co.uk/java/traps/java_double_traps.html

中使用浮点运算相关的微小细节

还有一个指向使用BigDecimal的问题的链接。强烈建议您同时阅读它们。它真的帮助了我。 享受,博罗。

答案 3 :(得分:0)

计算机上的双重表示是正常的。你失去了一些,然后你会得到这样的结果。更好的解决方案是:

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

答案 4 :(得分:0)

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

在计算机中,只有固定数量的位可用于表示值。这意味着它可以容纳有限数量的值。但是有无穷无尽的实数,因此并非所有数字都可以完全表示。但通常价值是接近的。您可以找到更详细的解释here

答案 5 :(得分:0)

这是因为IEEE754二进制格式的限制可以充分利用32位。

答案 6 :(得分:0)

当我们手工处理浮点数时,人们习惯于在'基数10'中思考(也就是说,在将它们写在纸上或将它们输入计算机时)。因此,我们可以写下17%的精确表示。我们只写0.17(或1.7E-1等)。试图用这个系统来代表这样一个微不足道的东西是不可能完全用那个系统完成的,因为我们必须写0.3333333 ...用无限数量的3s,这是不可能的。

处理浮点的计算机不仅具有有限数量的位来表示数字的尾数(或有效数字),它们也被限制为以2为基数表示尾数。这意味着大多数百分比(我们人类的基础10浮点约定始终可以写完全,例如'0.17')不可能,以便计算机准确存储。像0%,25%,50%,75%和100%这样的分数可以表示为正好作为计算机中的浮点数,因为它由一半(2E-1)或四分之一组成( 2E-4)非常适合数字的数字表示。对于计算机存储的百分比值,例如17%或甚至是微不足道的(对于我们人类!!),例如10%或1%,对于二进制浮点系统来说,“三分之一”的含义是不可能的。人(基础10)浮点系统。

但是如果你仔细选择你的浮点值,那么它们总是由整数1/2 ^ n组成,其中n可能是10(意味着整数为1/1024),那么它们总是可以存储完全没有错误作为浮点数。因此,如果您尝试将17/1024存储在计算机中,它将顺利进行。即使使用“人类基础10”十进制系统,你也可以毫无错误地存储它(但是你可以通过你必须处理的实际数字来确定它。)

这是我相信为什么有些游戏在整个360度转弯为256角度单位的单位中表达角度的原因。可以毫无损失地表示为0到1之间的浮点数(其中1意味着你完全旋转)。

答案 7 :(得分:0)

正如其他人所指出的那样,只有两个权力组合的数字才能以(双边)浮点格式完全表示

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

如果问题只是显示问题,那么您可以在显示数字的方式中找到答案。例如:

  

String.format(“%。2f”,n)

会将数字格式化为2位小数。