浮点加法 – 给出奇怪的结果..!
执行以下代码时:
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还尝试在二进制处理器上使用十进制计数系统; 因此,它的计算效率低于基于双/浮点的计算
如果你需要精确的计算,比如当你使用非常敏感的数据时,不要使用float
或double
,它们在二进制中的表示使用近似值。 查看这篇文章以获得一些很好的解释。
这是一种常见的误解。 这种“错误”与浮点数据结构有关:读这个 。 在这种情况下,您可以使用double
来获得更高的精度。