为什么在Python3中str(float)返回的数字比Python2多?

为什么在Python3中str(float)返回的数字比Python2多?,python,python-2.7,python-3.x,floating-point-conversion,Python,Python 2.7,Python 3.x,Floating Point Conversion,在Python2.7中,repr的float返回最接近的十进制数,最长可达17位;这足够精确,可以唯一标识每个可能的IEEE浮点值str的工作原理类似,只是它将结果限制为12位;在大多数情况下,这是一个更合理的结果,并将您与二进制和十进制表示之间的细微差异隔离开来 Python 2演示: 在Python3.2中,str和repr返回相同的内容 Python 3演示: 是否有描述变更的政治公众人物或负责人的其他声明?不,没有政治公众人物。bug追踪器中有一个,Python开发人员邮件列表中有一个。

在Python2.7中,
repr
float
返回最接近的十进制数,最长可达17位;这足够精确,可以唯一标识每个可能的IEEE浮点值<一个
float
的code>str的工作原理类似,只是它将结果限制为12位;在大多数情况下,这是一个更合理的结果,并将您与二进制和十进制表示之间的细微差异隔离开来

Python 2演示:

在Python3.2中,
str
repr
返回相同的内容

Python 3演示:


是否有描述变更的政治公众人物或负责人的其他声明?

不,没有政治公众人物。bug追踪器中有一个,Python开发人员邮件列表中有一个。虽然我负责提出并实施这一改变,但我不能说这是我的想法:它是在2010年欧罗皮顿与Guido的对话中产生的

更多细节:如评论中所述,Python3.1为float的字符串
repr
引入了一种新的算法(后来后移植到Python2系列,因此它也出现在Python2.7中)。这种新算法的结果是,在提示符处键入的“短”十进制数具有相应的短表示形式。这消除了造成
str
repr
之间差异的现有原因之一,并使
str
repr
可以使用相同的算法。因此,对于Python3.2,在上面的讨论之后,
str
repr
是相同的。至于原因:它使语言变得更小更干净,并且在输出字符串时删除了12位数字的任意选择。(顺便说一句,在2.7之前的Python版本中,
repr
使用的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]
我敢肯定,对于这种现象,至少有一个StackOverflow问题在问:,还有最近的一个。通过Python 3.2中引入的简化,我们得到了以下结果:

>>> x = 1.4 * 1.5
>>> print(x)
2.0999999999999996
>>> print([x])
[2.0999999999999996]
这至少更加一致

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

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

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

看起来这个问题可能与此相关。在(最后一个要点)中还有一个关于此更改的注释。我想这是一个:Python 3.1添加了一个新特性,通过舍入到浮点的一个ε内的最短小数点来隐藏不相关的舍入错误,而不是最近的小数点,因此,12位数的黑客不再是必要的。@abarnert我认为我的简短示例显示了这种想法的谬误。您提供的链接似乎只关心哪些测试将要中断,而不是一开始它是否是一个好主意;也许邮件列表的讨论有更多的理由。@MarkRansom:在这种情况下,12位数的黑客攻击是错误的,你可以从
2.099999996==2.1
中看出。当然,有时您可能需要这种不精确性,尽管它不是无关紧要的,但有时您也只需要2个数字,当然Python提供了显式和轻松地实现这一点的方法,它只是没有隐式地实现。无论如何,如果您想就基本原理进行争论或试图更改Python,那么这里就不是这样做的地方。无论卢卡斯和格奥尔格(不是我)发表的文章中的论点是否谬误,它们都是论点。谢谢你提供的信息,这正是我想要的。我只是希望有一个与
g
格式规范等价的规范,它不会随意转换为科学符号,我因此避免使用它;我经常希望字符串格式更易于配置。也许有一天吧。我不确定我是否接受这样的论点,即对象的输出需要与包含该对象的列表的输出相同,但对于包含不可打印字符的字符串,情况仍然不是这样:
>>> x = 1.4 * 1.5
>>> print(x)
2.0999999999999996
>>> print([x])
[2.0999999999999996]
>>> print("{:.12g}".format(x))
2.1