所以我认为我基本上理解浮点数是如何工作的以及为什么我们不能为某些操作得到“精确”的结果。
我对this SO-question感到困惑,其中@MikeMüller建议四舍五入。
我的理解如下。
如果我们写小数位,它看起来像这样:
1000 100 10 1 . 1/10 1/100 1/1000
二进制看起来像这样:
8 4 2 1 . 1/2 1/4 1/8
因此我们将0.5或0.25或0.125精确地存储在内存中但不是例如0.3
那么为什么python输出如下:
print(0.1)
print(0.2)
print(0.3)
print(0.1 + 0.2)
>>>0.1
>>>0.2
>>>0.3
>>>0.30000000000000004
我认为应该输出
>>>0.1
>>>0.2
>>>0.30000000000000004
>>>0.30000000000000004
我哪里错了?
我的问题不是Is floating point math broken?的重复 因为OP不明白为什么0.1 + 0.2!= 0.3。这不是我的问题!
答案 0 :(得分:11)
由于它们不相同,因此0.1
和0.2
尚未正确表示。所以:
>>>print("%.20f" % (0.1+0.2))
0.30000000000000004441
>>>print("%.20f" % 0.3)
0.29999999999999998890
>>>print(0.29999999999999998890)
0.3
因此,它完全取决于打印内容的Python规则,特别是考虑到纯0.3
表示比实际0.3
更接近0.1 + 0.2
。
以下是Python docs的相关摘录:
有趣的是,有许多不同的十进制数字共享 最接近的近似二进制分数。例如,数字
0.1
和0.10000000000000001
和0.1000000000000000055511151231257827021181583404541015625
全部由3602879701896397 / 2 ** 55
近似。由于所有这些小数 值共享相同的近似值,其中任何一个都可以 在保留不变eval(repr(x)) == x
时显示。历史上,Python提示符和内置
repr()
函数会 选择具有17位有效数字的0.10000000000000001
。 从Python 3.1开始,Python(在大多数系统上)现在能够 选择最短的,只需显示0.1
。
答案 1 :(得分:1)
来自the docs on floating point in Python 3,
有趣的是,有许多不同的十进制数共享相同的最接近的近似二进制分数。例如,数字0.1和0.10000000000000001和0.1000000000000000055511151231257827021181583404541015625都近似为3602879701896397/2 ** 55.由于所有这些十进制值共享相同的近似值,因此可以显示其中任何一个,同时仍保留不变eval(repr(x) )== x。
历史上,Python提示符和内置的repr()函数将选择具有17位有效数字的那一个,即0.10000000000000001。从Python 3.1开始,Python(在大多数系统上)现在能够选择最短的这些并且只显示0.1。
这就是为什么它可以显示0.3
的原因 - 因为这是存储为二进制表示的最短字符串。 0.1 + 0.2
稍微高一点的结果不能显示为比0.30000000000000004
更短的字符串。
答案 2 :(得分:-1)
为了使舍入问题不可见,通常浮点数打印时没有最后一位数字,这是圆形的。这正是为了隐藏您希望看到的问题。
因此,0.30000000000000004将四舍五入为0.3。
但如果您故意进行这样的计算以避免这种舍入,您可以轻松地重现该问题。例如,使用1e + 6的结果多次。你会看到,你看到了什么。