为什么str(float)在Python 3中返回的数字比Python 2多?

时间:2014-09-17 19:25:05

标签: python python-2.7 python-3.x floating-point-conversion

在Python 2.7中,repr的{​​{1}}返回最接近17位数的最接近的十进制数;这足够精确,可以唯一地标识每个可能的IEEE浮点值。 float的{​​{1}}工作方式类似,但它将结果限制为12位数;对于大多数用途,这是一个更合理的结果,并使您免受二进制和十进制表示之间的细微差别。

Python 2演示:http://ideone.com/OKJtxv

str

在Python 3.2中显示floatprint str(1.4*1.5) 2.1 print repr(1.4*1.5) 2.0999999999999996 返回相同的内容。

Python 3演示:http://ideone.com/oAKRsb

str

是否有PEP描述了变更或其他负责人的陈述?

1 个答案:

答案 0 :(得分:28)

不,没有PEP。错误跟踪器中有issue,Python开发人员邮件列表中有associated discussion。虽然我负责提出并实施变更,但我不能说这是我的想法:它是在与Guido在EuroPython 2010上的对话中产生的。

更多细节:正如在评论中已经提到的,Python 3.1为float的字符串repr引入了一种新算法(后来反向移植到Python 2系列,因此它也出现在Python 2.7中)。作为这种新算法的结果,在提示符处键入的“短”十进制数具有相应的短表示。这消除了strrepr之间存在差异的现有原因之一,并且可以对strrepr使用相同的算法。因此,对于Python 3.2,在上面链接的讨论之后,strrepr变得相同。至于为什么:它使语言变得更小更清洁,并且在输出字符串时它删除了相当任意的12位数选择。 (在2.7之前的Python版本中,用于repr的17位数的选择远非任意,顺便说一下:两个不同的IEEE 754 binary64浮点数在转换为带有17位有效数字的十进制时将具有不同的表示形式,并且17是具有此属性的最小整数。)

除了简单之外,还有一些不太明显的好处。 reprstr区别的一个方面是,repr自动在容器中使用,这一点在过去一直让用户感到困惑。例如,在Python 2.7中:

>>> x = 1.4 * 1.5
>>> print x
2.1
>>> print [x]
[2.0999999999999996]

我确信至少有一个StackOverflow问题在某个地方询问这个现象:here is one suchanother更新的问题。通过Python 3.2中引入的简化,我们得到了这个:

>>> x = 1.4 * 1.5
>>> print(x)
2.0999999999999996
>>> print([x])
[2.0999999999999996]

至少更一致。

如果您确实希望能够隐藏不精确,那么正确的方法仍然是相同的:使用字符串格式来精确控制输出格式。

>>> print("{:.12g}".format(x))
2.1

我希望这能解释改变背后的一些原因。我不打算认为这是普遍有益的:正如你所指出的,旧str具有隐藏不精确的方便副作用。但在我看来(当然,我有偏见),它确实有助于从语言中消除一些惊喜。