简体   繁体   English

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

[英]Why does str(float) return more digits in Python 3 than Python 2?

In Python 2.7, repr of a float returns the nearest decimal number up to 17 digits long;在 Python 2.7 中, float repr返回最接近的十进制数,最长可达 17 位; this is precise enough to uniquely identify each possible IEEE floating point value.这足够精确以唯一标识每个可能的 IEEE 浮点值。 str of a float worked similarly, except that it limited the result to 12 digits; float str工作方式类似,不同之处在于它将结果限制为 12 位; for most purposes this is a more reasonable result, and insulates you from the slight differences between binary and decimal representation.对于大多数用途,这是一个更合理的结果,并且可以避免二进制和十进制表示之间的细微差别。

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

print str(1.4*1.5)
2.1
print repr(1.4*1.5)
2.0999999999999996

In Python 3.2 it appears str and repr return the same thing.在 Python 3.2 中,似乎strrepr返回相同的内容。

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

print(str(1.4*1.5))
2.0999999999999996
print(repr(1.4*1.5))
2.0999999999999996

Is there a PEP that describes the change, or some other statement from someone responsible?是否有描述变更的 PEP,或负责人的其他声明?

No, there's no PEP.不,没有 PEP。 There's an issue in the bug tracker, and an associated discussion on the Python developers mailing list.错误跟踪器中存在一个问题,以及 Python 开发人员邮件列表上的相关讨论 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.虽然我负责提出和实施更改,但我不能声称这是我的想法:它是在 2010 年 EuroPython 上与 Guido 的对话中出现的。

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).更多细节:正如评论中已经提到的,Python 3.1 为浮点数的字符串repr引入了一种新算法(后来向后移植到 Python 2 系列,因此它也出现在 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 .这消除之间的差额现有的原因之一strrepr ,并有可能使用相同的算法既strrepr So for Python 3.2, following the discussion linked to above, str and repr were made identical.因此,对于 Python 3.2,按照上面链接的讨论, strrepr是相同的。 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.至于为什么:它使语言更小更干净,并且在输出字符串时删除了相当随意的 12 位数字选择。 (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.) (顺便说一下,在 2.7 之前的 Python 版本中,选择用于repr的 17 位数字远非任意:两个不同的 IEEE 754 binary64 浮点数在转换为具有 17 位有效数字的十进制时将具有不同的表示形式,而 17 是最小的整数与此属性。)

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.过去让用户感到困惑的reprstr区别的一个方面是repr自动在容器中使用这一事实。 So for example in Python 2.7:因此,例如在 Python 2.7 中:

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

I'm sure there's at least one StackOverflow question asking about this phenomenon somewhere: here is one such , and another more recent one.我敢肯定至少有一个 StackOverflow 问题在某处询问这种现象:这是一个这样的另一个是最近的。 With the simplification introduced in Python 3.2, we get this instead:随着 Python 3.2 中引入的简化,我们得到了这个:

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

which is at least more consistent.这至少更一致。

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

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.我不会争辩说它普遍有益:正如您指出的那样,旧的str具有隐藏不精确性的便利副作用。 But in my opinion (of course, I'm biased), it does help eliminate a few surprises from the language.但在我看来(当然,我有偏见),它确实有助于消除语言中的一些惊喜。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM