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

Mar*_*som 23 python python-2.7 python-3.x floating-point-conversion

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

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

print str(1.4*1.5)
2.1
print repr(1.4*1.5)
2.0999999999999996
Run Code Online (Sandbox Code Playgroud)

在Python 3.2中它出现strrepr返回相同的东西.

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

print(str(1.4*1.5))
2.0999999999999996
print(repr(1.4*1.5))
2.0999999999999996
Run Code Online (Sandbox Code Playgroud)

是否存在描述变更的PEP或负责人的其他声明?

Mar*_*son 33

不,没有PEP.错误跟踪器中存在一个问题,以及Python开发人员邮件列表上的相关讨论.虽然我负责提出和实施变更,但我不能说这是我的想法:它是在与Guido在EuroPython 2010上的对话中产生的.

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

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

>>> x = 1.4 * 1.5
>>> print x
2.1
>>> print [x]
[2.0999999999999996]
Run Code Online (Sandbox Code Playgroud)

我确定至少有一个StackOverflow问题在某个地方询问这个现象:这是一个这样的,另一个是最近的一个.通过Python 3.2中引入的简化,我们得到了这个:

>>> x = 1.4 * 1.5
>>> print(x)
2.0999999999999996
>>> print([x])
[2.0999999999999996]
Run Code Online (Sandbox Code Playgroud)

至少更一致.

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

>>> print("{:.12g}".format(x))
2.1
Run Code Online (Sandbox Code Playgroud)

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