【发布时间】:2021-08-29 07:10:10
【问题描述】:
我知道使用二进制表示不可能精确地表示浮点数(我也理解为什么 0.1 + 0.2 == 0.3 是错误的)。现在,当我尝试尝试不同的浮动算术案例时,我陷入了困境:
查看十进制数转换为二进制格式的方式,我得出结论,在十进制表示中具有相同小数部分的两个数字(例如:0.3 和 1.3)在转换为二进制格式后将具有相同的小数部分。
为了测试这一点,我在 python 中尝试了以下代码:
print(f"{0.3:.20f}")
print(f"{1.3:.20f}")
0.29999999999999998890
1.30000000000000004441
我不明白为什么小数部分会有所不同,所以为了更好地了解情况,我尝试了这个:
print(f"{0.3:.20f}")
print(f"{1 + 0.3:.20f}")
print(f"{1.3:.20f}")
0.29999999999999998890
1.30000000000000004441
1.30000000000000004441
问题:既然 1 不是一个近似数(因为可以将 1 以精确的二进制形式表示为 2^0),那么为什么加 1 会改变数字的小数部分?
此外,当我们从 1.3 中减去 1 时,为什么结果值不等于 0.3
print(f"{1.3:.20f}")
print(f"{1.3 - 1:.20f}")
print(f"{0.3:.20f}")
1.30000000000000004441
0.30000000000000004441
0.29999999999999998890
我的整个问题可以总结为以下并列:
print(1 + .3 == 1.3)
print(0.3 == 1.3 -1)
True
False
【问题讨论】:
-
@KlausD。我不认为这是一个骗局。 OP 似乎了解什么是二进制浮点表示及其局限性。他们在询问这个特定的现象
-
回复:“为什么加 1 会改变数字的小数部分?”舍入。
-
这是由于使用了相应的标准(如 IEEE_754)导致的舍入截止值不同,如链接(重复)问题中所述。换句话说,有一个程序可以将分数转换为四舍五入的小数,这与具有不同整数部分但小数部分相同的分数不一致,正如您在 1.3 和 0.3 中注意到的那样,x.3 中的 .3 以不同的方式四舍五入取决于 x。
-
@j1-lee 舍入是否会导致有限精度浮点运算的结果与天真预期的结果不同取决于操作数的具体情况,例如,它们的相对大小(例如具体示例,请参见 Sterbenz 引理,减法抵消)。有时结果符合天真的期望,有时则不然。为了解决这个问题,我建议手动模拟有问题的二进制算术运算,一切都会变得清晰。
-
@Gravity 这是因为 njuffa 在他们上面的评论中解释的,“有时结果符合天真的期望,有时则不然。”;浮点数上的算术运算与您所期望的朴素算术运算不同。您可以使用ecs.umass.edu/ece/koren/arith/simulator/FPAdd/ 进行加减运算,h-schmidt.net/FloatConverter/IEEE754.html 进行转换。确实,我得到了0.3 + 1.0 == 1.3, 1.3 - 1.0 != 0.3。
标签: python floating-point