为什么0.1有时能准确打印,有时却不能?

sam*_*sam 2 python floating-point

我跑:

print(0.1)
print(0.2)
print(0.3)
print(0.4)
print(0.5)
print(0.5-0.4)
print(0.4-0.3)
print(0.3-0.2)
print(0.2-0.1)
Run Code Online (Sandbox Code Playgroud)

表明:

0.1
0.2
0.3
0.4
0.5
0.09999999999999998
0.10000000000000003
0.09999999999999998
0.1
Run Code Online (Sandbox Code Playgroud)

为什么直接打印数字可以,但使用运算符-会得到意想不到的值?

我已经检查过: 浮点数学是否损坏?

如果0.5-0.4不能精确地保存在硬件中,为什么打印(0.1)会显示0.1而不是0.10000000000xxx?

也许更明确的说法是:

根据我的理解,python 应该 print(0.1) 为 0.10000000000xxx,而 0.5-0.4 应该等于 0.4-0.3 并等于 0.3-0.2,对吧?

为什么Python可以“Python通过显示舍入值来保持位数的可管理性”?如果python想要print(0.1)为0.1,那么它应该将0.4-0.3视为0.1,对吧?为什么Python希望我们在这类话题上感到困惑?

为了更精确地说明这个问题“不是”,真正认为 0.5-0.4 != 0.4-0.3。我的主要问题是 print(0.1)= 0.1 而不是 0.10000000000xxxx,为什么 python 可以执行这种操作?它会让我们对“浮点数学坏了吗?”感到非常困惑。

jua*_*aga 5

因为数量不相等。当您直接传递floattoDecimal以获得更好地表示正在发生的情况时,请考虑以下事项:

>>> from decimal import Decimal
>>> Decimal(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> Decimal(0.5 - 0.4)
Decimal('0.09999999999999997779553950749686919152736663818359375')
Run Code Online (Sandbox Code Playgroud)

请注意,从文字中获得的实际浮点值与从文字和0.1创建的浮点数相减的结果不同。这是因为两个文字也可能有错误(注意,可以精确表示,因为它可以表示为 2 的幂)。0.50.40.5

>>> Decimal(0.5)
Decimal('0.5')
>>> Decimal(0.4)
Decimal('0.40000000000000002220446049250313080847263336181640625')
Run Code Online (Sandbox Code Playgroud)

请注意,当您打印数字时,Python 打印的字符串更像是一个近似值,尽管 Python 使用的算法应该生成最短的表示形式,可以可靠地从文字中重现实际的浮点值:

>>> 0.5 - 0.4
0.09999999999999998
>>> Decimal(0.09999999999999998)
Decimal('0.09999999999999997779553950749686919152736663818359375')
>>> Decimal(0.5 - 0.4)
Decimal('0.09999999999999997779553950749686919152736663818359375')
Run Code Online (Sandbox Code Playgroud)

请注意,我能想到的几乎所有语言都使用实际在硬件中表示的浮点数的截断形式。如果你想看到更多,通常必须使用字符串格式。

  • 我只是补充一下“0.1 == 0.2 - 0.1”实际上是“True”。虽然“0.1”和“0.2”都无法准确表示,但“0.2”精确地表示为“0.1”的 2 倍。这是因为这两个数字具有相同的尾数,仅指数不同。这就是为什么这个特定的减法的行为与其他减法不同。 (3认同)
  • @sam 打印的字符串表示形式是*可靠地再现实际浮点的最短表示形式*(尽管这是 CPython 实现细节,只要它可靠,我认为它不必是最短的) ) (2认同)
  • @sam:这在一定程度上是Python 3中两个设计决策的结果:首先,浮点数的`repr`应该是“忠实的”(也就是说,不同的浮点数应该有不同的`repr`),第二, “float”的“str”和“repr”应该相同。从这些选择可以看出,如果两个(非 NaN)浮点数比较不相等,那么它们将以不同的方式“打印”。请注意,Python 2 做出了不同的选择,在 Python 2 中,“print(0.5 - 0.4)”将给出与“print(0.1)”相同的输出,尽管打印的两个值并不相等。 (2认同)