参见英文答案 >
How to resolve a Java Rounding Double issue13个
这个简单的“双”计算在java中有什么问题?
这个简单的“双”计算在java中有什么问题?
我知道一些十进制数字不能正确地用浮点/双二进制格式表示,但是使用变量d3,java能够存储和显示2.64没有任何问题.
double d1 = 4.64; double d2 = 2.0; double d3 = 2.64; double d4 = d1 - d2; System.out.println("d1 : " + d1); System.out.println("d2 : " + d2); System.out.println("d3 : " + d3); System.out.println("d4 : " + d4); System.out.println("d1 - d2 : " + (d1 - d2));
回答,
d1 : 4.64 d2 : 2.0 d3 : 2.64 d4 : 2.6399999999999997 d1 - d2 : 2.6399999999999997
解决方法
问题
在二进制2.64是10.10100011110101110000101000111101循环,换句话说,不能在二进制中表示,因此小错误. Java对d3很好,但是一旦实际的计算涉及到它就必须落在真实的表现上.
更多:
2.64= 10.10100011110101110000101000111101 4.64=100.1010001111010111000010100011110
现在,即使在这两种情况下,.64都是一样的,因为4 = 100使用了比2 = 10更多的双重有效数字,所以当你说4.64-2.0和2.64的.64在这两种情况下用不同的舍入误差表示,这个丢失的信息无法恢复为最终答案.
注:我在这里没有使用双重数字的重要数字,无论二进制计算器将产生什么,然而效果是相同的,无论数字的有效数字
不要假设双重值是准确的(尽管它们的不准确性是微观的,只是因为某些数字不能用二进制表示).
浮点数并不准确,但只能从小数点看
虽然你应该总是期望双精度在最后几个小数位将会有小的错误,但将二进制表示视为“坏”或更差的十进制是错误的.
我们都习惯了某些数字(例如1/3)不能十进制表示,我们接受这样一个数字将最终为0.333333333333,而不是真正的值(我无法写下无限空间);在这种情况下,二进制数不能被精确表达. 1/10是不能用二进制精确表达的数字;这只是因为我们习惯了十进制