Java 我知道0.1D+;0.2D==0.300000000004d——为什么为0.1D+;0.1D==0.2D?

Java 我知道0.1D+;0.2D==0.300000000004d——为什么为0.1D+;0.1D==0.2D?,java,floating-point,ieee-754,Java,Floating Point,Ieee 754,0.1d、0.2d或0.3d都不能用二进制精确表示 为什么在Java中0.1D+0.1D==0.2D是真的 64位二进制数是如何变为0.1,0.2,0.3?????代码在哪里?如果运行: System.out.println(new BigDecimal(0.1d + 0.1d)); System.out.println(new BigDecimal(0.2d)); System.out.println(0.1d + 0.1d == 0.2d); //true 您将看到这两条语句都打印0.20

0.1d、0.2d或0.3d都不能用二进制精确表示

为什么在Java中
0.1D+0.1D==0.2D
是真的

64位二进制数是如何变为0.1,0.2,0.3?????代码在哪里?如果运行:

System.out.println(new BigDecimal(0.1d + 0.1d));
System.out.println(new BigDecimal(0.2d));
System.out.println(0.1d + 0.1d == 0.2d); //true
您将看到这两条语句都打印
0.2000000000011102230246256540423631668090908203125

换句话说,
0.1d+0.1d==0.2d
为真,但两者都不严格等于十进制数0.2

另一方面,下面的前两行不打印相同的数字,
0.1d+0.1d+0.1d==0.3d
为假:

System.out.println(new BigDecimal(0.1d + 0.1d + 0.1d));
System.out.println(new BigDecimal(0.3d));
System.out.println(0.1d + 0.1d + 0.1d == 0.3d); //false

假设
x
是精确的小数。
最近浮点数(x)
是到浮点的转换。
它四舍五入到最接近的可表示浮点值,与偶数相等。
ulp(最接近的浮点数(x))
是浮点值的最小精度单位(即有效位的最小位的值)。
x+y
表示精确的算术运算,与-*/相同。
最近浮点数(x)+最近浮点数(y)
是浮点数近似值的精确和。
最近浮点数(最近浮点数(x)+最近浮点数(y))
是浮点运算

操作
最近的浮点数(x)+最近的浮点数(x)
严格等同于
最近的浮点数(x)*2
,操作
最近的浮点数(x)*2
是精确的,除了浮点溢出的罕见情况:它只是指数的移动,
最近的浮点数(2*最近的浮点数(x))=2*最近的浮点数(x)


我们有这样一个属性:
abs(nearest_float(x)-x)实际上不是一个重复的-op似乎已经知道,不是所有的十进制数都可以用双精度表示…nearest_float(x)+nearest_float(x)=nearest_float(2*x)在IEEE 754中无论使用何种语言都是正确的。我们无法解释为什么在评论中。。。可能问题提前关闭。@aka.nice重新打开,如果您想添加答案。为什么我定义双d=0.2,我看到的值是0.2,而不是0.200000000001110223024625156404236316680908203125。您看到0.2,因为double.toString“舍入”双d。要查看确切的值,请使用我的示例中的BigDecimal@成一丁 您最多有2^64个不同的浮点值(其中有许多N)。它是有理分数的有限子集。如此多的小数将四舍五入到同一个浮点数。您看到的是最短的十进制表示法,它将舍入到相同的浮点值,而不是精确的分数值。