这个简单的"双重"计算有什么问题?

vi.*_*su. 10 java double-precision

在java中这个简单的"双重"计算有什么问题?

我知道一些十进制数字不能正确地用float/double二进制格式表示,但是使用变量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));
Run Code Online (Sandbox Code Playgroud)

回答,

d1      : 4.64
d2      : 2.0
d3      : 2.64
d4      : 2.6399999999999997
d1 - d2 : 2.6399999999999997
Run Code Online (Sandbox Code Playgroud)

Ric*_*gle 17

问题

在二进制2.64中是10.10100011110101110000101000111101重复出现,换句话说,二进制不能完全表示,因此误差很小.Java对d3很友好,但只要涉及实际计算,它就必须依赖于实际表示.

二进制计算器

更多:

2.64= 10.10100011110101110000101000111101
4.64=100.1010001111010111000010100011110 
Run Code Online (Sandbox Code Playgroud)

现在,即使.64在两种情况下都是相同的,它仍然保持不同的精度,因为4 = 100使用了更多的双重有效数字而不是2 = 10,所以当你说4.64-2.0和2.64时.64在两种情况下都表示不同的舍入误差,这些丢失的信息无法在最终答案中恢复.

NB我在这里没有使用double有效数字的数量,只要二进制计算器会产生什么,但无论有效数字是多少,效果都是一样的

永远不要假设双值是精确的(虽然它们的不准确性是微观的,只是因为某些数字不能用二进制精确表示).


浮点数不精确,但仅从小数的角度来看

虽然你应该总是期望双精度在最后几个小数位上会有小错误,但将二进制表示视为"坏"或更糟糕的十进制是错误的.

我们都习惯于某些数字(比如1/3)在十进制中不能完全表示,我们接受这样的数字将最终为0.333333333333而不是真值(我无法在没有无限空间的情况下写下来); 在这种情况下,二进制数不能准确表达.1/10是一个不能用二进制精确表示的数字; 这只会让我们感到惊讶,因为我们习惯于小数

  • 真棒的实际答案. (3认同)

Sca*_*bat 0

没有什么问题。但尝试使用 BigDecimal

http://docs.oracle.com/javase/6/docs/api/java/math/BigDecimal.html

注意:根据 IEEE 标准 754,double 和 float 在内部表示为二进制分数,因此不能准确表示十进制分数

  • 2.64 的 BigDecimal ?? :) (2认同)