浮点加法 – 给出奇怪的结果..!

执行以下代码时:

public class FPoint { public static void main(String[] args) { float f = 0.1f; for(int i = 0; i<9; i++) { f += 0.1f; } System.out.println(f); } } 

将显示以下输出:

1.0000001

但输出应该是1.0000000 ,对吗? 如我错了请纠正我..!!

对于IEEE 754标准,0.1不是真正的“0.1”。

0.1编码: 0 01111011 10011001100110011001101 (带浮点数)

  • 0是符号(=正数)
  • 01111011指数(= 123 – > 123 – 127 = -4 (127是IEEE 754中的偏差 ))
  • 10011001100110011001101尾数

要以十进制数转换尾数,我们有1.10011001100110011001101 * 2 ^ -4 (base2)[1.xxx隐含在IEEE 754中]

= 0.000110011001100110011001101(base2)

= 1/2 ^ 4 + 1 ^ 2 ^ 5 + 1/2 ^ 8 + 1/2 ^ 9 + 1/2 ^ 12 + 1/2 ^ 13 + 1/2 ^ 16 + 1/2 ^ 17 + 1 / 2 ^ 20 + 1/2 ^ 21 + 1/2 ^ 24 + 1/2 ^ 25 + 1/2 ^ 27(base10)

= 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + 1/131072 …(base10)

= 0.10000000149011612 (base10)

就像我们的十进制系统中的某些实数(如1/3)无法准确表达一样,某些数字(如1/10)无法用二进制精确表示。

 1/3=(decimal)0.33333333333 (3) recurring 1/10=(binary)0.00011001100 (1100) recurring 

因为我们对小数非常熟悉,所以很明显1/3不能准确表示,但对于具有基数为3的系统的人来说,这似乎是对小数的一个主要限制;

 1/3=(base 3)0.1 

因为这样的1/10在浮点数中不精确地表示,并且通过将多个不精确的数字加在一起,你会得到一个不准确的答案。

在此上下文中,您应该解释浮点错误。 如果您有一个在十进制内可以完全表示但不在二进制内的数字,那么您可能会发现BigDecimal很有用。 但是你不应该认为BigDecimal比浮点数更好; 它只是有一组不同的数字,它不能完全代表; 你习惯的那套。 BigDecimal还尝试在二进制处理器上使用十进制计数系统; 因此,它的计算效率低于基于双/浮点的计算

如果你需要精确的计算,比如当你使用非常敏感的数据时,不要使用floatdouble ,它们在二进制中的表示使用近似值。 查看这篇文章以获得一些很好的解释。

这是一种常见的误解。 这种“错误”与浮点数据结构有关:读这个 。 在这种情况下,您可以使用double来获得更高的精度。