【问题标题】:Why does str(float) return more digits in Python 3 than Python 2?为什么 str(float) 在 Python 3 中返回的位数比 Python 2 多?
【发布时间】:2014-09-17 19:25:05
【问题描述】:

在 Python 2.7 中,float 中的 repr 返回最接近的十进制数,最长为 17 位;这足以精确地识别每个可能的 IEEE 浮点值。 strfloat 的工作方式类似,只是它将结果限制为 12 位;在大多数情况下,这是一个更合理的结果,并使您免受二进制和十进制表示之间的细微差别。

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

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

在 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

是否有描述变更的 PEP 或来自负责人的其他声明?

【问题讨论】:

  • 看起来问题#1580 可能与此处相关。 What’s New In Python 3.1: Other Language Changes(最后一个要点)中也有关于此更改的注释。
  • 我猜是这个:bugs.python.org/issue9337
  • Python 3.1 添加了一项新功能,通过舍入到浮点数的一个 epsilon 内的 最短 小数而不是 最接近的,来隐藏不相关的舍入错误>,因此不再需要 12 位破解。
  • @abarnert 我认为我的简短示例显示了这种想法的谬误。您提供的链接似乎只与将要中断的测试有关,而不是首先是否是一个好主意;也许邮件列表讨论更有理由。
  • @MarkRansom:嗯,在这种特殊情况下,12 位数的破解是错误的,正如您在2.0999999999999996 == 2.1 中看到的那样。当然,有时您可能想要这种不精确性,即使它不是无关紧要的,但有时您也只想要 2 位数字,当然 Python 提供了明确且轻松地做到这一点的方法,它只是没有隐式地做到这一点。无论如何,如果您想争论基本原理或尝试更改 Python,这不是这样做的地方。无论 Lukas 和 georg(不是我)发布的问题中的论点是否谬误,它们都是论点。

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


【解决方案1】:

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

更多细节:正如 cmets 中已经提到的,Python 3.1 为浮点数的字符串 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 具有隐藏不精确性的方便副作用。但在我看来(当然,我有偏见),它确实有助于消除语言中的一些惊喜。

【讨论】:

  • 感谢您的信息,这正是我想要的。我只是希望有一个与g 格式规范等效的格式规范,它不会随意切换到科学记数法,因此我避免使用它。
  • 同意;我经常希望字符串格式更易于配置。也许有一天。
  • P.S.我不确定我是否认为对象的输出需要与包含该对象的列表的输出相同,对于包含不可打印字符的字符串来说,仍然不是这样:@987654325 @
猜你喜欢
  • 2011-12-19
  • 1970-01-01
  • 2015-10-11
  • 2023-01-16
  • 2012-04-06
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
相关资源
最近更新 更多