为什么 str(float) 在 Python 3 中返回的位数比 Python 2 多?
问题描述
在 Python 2.7 中,float
的 repr
返回最接近的十进制数,最长为 17 位;这足以精确地识别每个可能的 IEEE 浮点值.float
的 str
的工作方式类似,只是它将结果限制为 12 位;在大多数情况下,这是一个更合理的结果,并使您免受二进制和十进制表示之间的细微差别.
In Python 2.7, repr
of a float
returns the nearest decimal number up to 17 digits long; this is precise enough to uniquely identify each possible IEEE floating point value. str
of a float
worked similarly, except that it limited the result to 12 digits; for most purposes this is a more reasonable result, and insulates you from the slight differences between binary and decimal representation.
Python 2 演示:http://ideone.com/OKJtxv
Python 2 demo: http://ideone.com/OKJtxv
print str(1.4*1.5)
2.1
print repr(1.4*1.5)
2.0999999999999996
在 Python 3.2 中,str
和 repr
似乎返回相同的内容.
In Python 3.2 it appears str
and repr
return the same thing.
Python 3 演示:http://ideone.com/oAKRsb
Python 3 demo: http://ideone.com/oAKRsb
print(str(1.4*1.5))
2.0999999999999996
print(repr(1.4*1.5))
2.0999999999999996
是否有描述变更的 PEP 或来自负责人的其他声明?
Is there a PEP that describes the change, or some other statement from someone responsible?
解决方案
不,没有 PEP.错误跟踪器中有一个 issue 和一个 相关讨论.虽然我负责提出和实施更改,但我不能说这是我的想法:它是在 EuroPython 2010 上与 Guido 的对话中提出的.
No, there's no PEP. There's an issue in the bug tracker, and an associated discussion on the Python developers mailing list. While I was responsible for proposing and implementing the change, I can't claim it was my idea: it had arisen during conversations with Guido at EuroPython 2010.
更多细节:正如评论中已经提到的,Python 3.1 引入了一个新的算法,用于浮点的字符串 repr
,(后来向后移植到 Python 2 系列,因此它也出现在 Python 中2.7).作为这种新算法的结果,在提示符处键入的短"十进制数字具有相应的短表示.这消除了 str
和 repr
之间存在差异的现有原因之一,并使 str
和 使用相同的算法成为可能代码>代表代码>.所以对于 Python 3.2,按照上面链接的讨论,
str
和 repr
是相同的.至于为什么:它使语言更小更干净,并且在输出字符串时消除了相当随意的 12 位选择.(顺便说一下,在 2.7 之前的 Python 版本中,repr
使用的 17 位数字的选择远非任意:两个不同的 IEEE 754 binary64 浮点数在转换为具有 17 个有效数字的十进制时将具有不同的表示,而 17 是具有此性质的最小整数.)
Some more details: as already mentioned in comments, Python 3.1 introduced a new algorithm for the string repr
of a float, (later backported to the Python 2 series, so that it also appears in Python 2.7). As a result of this new algorithm, a "short" decimal number typed in at the prompt has a correspondingly short representation. This eliminated one of the existing reasons for the difference between str
and repr
, and made it possible to use the same algorithm for both str
and repr
. So for Python 3.2, following the discussion linked to above, str
and repr
were made identical. As to why: it makes the language a little bit smaller and cleaner, and it removes the rather arbitrary choice of 12 digits when outputting the string. (The choice of 17 digits used for the repr
in Python versions prior to 2.7 is far from arbitrary, by the way: two distinct IEEE 754 binary64 floats will have distinct representations when converted to decimal with 17 significant digits, and 17 is the smallest integer with this property.)
除了简单之外,还有一些不太明显的好处.repr
与 str
的区别在过去让用户感到困惑的一个方面是 repr
自动在容器中使用这一事实.例如在 Python 2.7 中:
Apart from simplicity, there are some less obvious benefits. One aspect of the repr
versus str
distinction that's been confusing for users in the past is the fact that repr
automatically gets used in containers. So for example in Python 2.7:
>>> x = 1.4 * 1.5
>>> print x
2.1
>>> print [x]
[2.0999999999999996]
我确信至少有一个 StackOverflow 问题在某处询问此现象:这是一个这样的,并且 另一个更新的.通过 Python 3.2 中引入的简化,我们得到了这个:
I'm sure there's at least one StackOverflow question asking about this phenomenon somewhere: here is one such, and another more recent one. With the simplification introduced in Python 3.2, we get this instead:
>>> x = 1.4 * 1.5
>>> print(x)
2.0999999999999996
>>> print([x])
[2.0999999999999996]
这至少更一致.
如果您确实希望能够隐藏不精确性,正确的做法保持不变:使用字符串格式化来精确控制输出格式.
If you do want to be able to hide imprecisions, the right way to do it remains the same: use string formatting for precise control of the output format.
>>> print("{:.12g}".format(x))
2.1
我希望这能解释这种变化背后的一些原因.我不会争辩说它是普遍有益的:正如您所指出的,旧的 str
具有隐藏不精确性的方便副作用.但在我看来(当然,我有偏见),它确实有助于消除语言中的一些惊喜.
I hope that explains some of the reasoning behind the change. I'm not going to argue that it's universally beneficial: as you point out, the old str
had the convenient side-effect of hiding imprecisions. But in my opinion (of course, I'm biased), it does help eliminate a few surprises from the language.
相关文章