![enter image description here](https://istack.dev59.com/eKzMd.webp)
It turns out that there are two ways to print every object: with full precision(as in the first result shown here)
, 但这个“with full precision”是什么意思呢?它可能在文本中为Python程序员提供非常简单的解释,但我似乎不太明白。It turns out that there are two ways to print every object: with full precision(as in the first result shown here)
, 但这个“with full precision”是什么意思呢?它可能在文本中为Python程序员提供非常简单的解释,但我似乎不太明白。这不是Python的问题,而是浮点数本质上的问题。事实证明,计算机在表示数字方面表现得很差。谁知道呢?
如果您有时间,我建议阅读《计算机科学家应该了解的浮点运算知识》。
现在,关于Python的实际问题,每个对象都有一个名为__str__
和一个名为__repr__
的方法。这些方法应该产生要在各种情况下显示的字符串。如果您在任何对象上使用内置的repr
或str
函数,或者在字符串格式化中使用"%r"
或"%s"
格式,您将看到这些字符串。当您在交互式提示符下评估某些内容时,默认会获得repr
。当您将某些内容传递给print
时,默认会获得str
。
浮点数对象的__repr__
被定义为以最大精度(至少在十进制下)表示它们,而它们的__str__
被定义为以更接近用户所需的形式显示。用户不想知道浮点数不是实数,因此不会向他们显示额外的精度。
repr(f)
的行为在3.1和2.7中发生了变化。
在2.7之前(包括Python 3.0),repr(f)
会给出最多17个有效数字,就像使用%17g
格式化一样。 IEEE-754浮点值具有53个有效二进制位,大约相当于16个十进制位。 17个有效数字保证每个二进制值产生不同的十进制值。
float
类型的x
的repr()
在很多情况下更短:它现在基于最短的十进制字符串,该字符串保证四舍五入后回到x
。与Python之前的版本一样,保证float(repr(x))
可以恢复x
。
str(f)
在Python 3.2中的行为发生了变化:
在2.x,3.0和3.1中:str(f)
会给出十进制值,舍入到仅有12个有效数字,就像使用%12g
格式化一样;精度由Objects/floatobject.h中的PyFloat_STR_PRECISION
宏控制。
在3.2+中,str(f)
的行为与repr(f)
完全相同——自从3.1以来,repr
输出更加人性化,而且由于str(f)
失去了精度,因此决定从Python 3.2开始,str(f)
应该与repr(f)
相同。
repr
行为的更改。旧行为如下:Python 2.6.8 (unknown, Jan 26 2013, 14:35:25)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3.1415 * 2
6.2830000000000004
>>>
而新行为是:
Python 2.7.3 (default, Mar 13 2014, 11:03:55)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3.1415 * 2
6.283
str
的旧行为是将值四舍五入到 12 个有效数字,导致信息丢失:Python 2.7.3 (default, Mar 13 2014, 11:03:55)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> str(0.1000000000000999)
'0.1'
>>> 0.1 == 0.1000000000000999
False
>>> repr(0.1000000000000999)
'0.1000000000000999'
repr
一样运作:Python 3.2.3 (default, Feb 20 2013, 14:44:27)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> str(0.1000000000000999)
'0.1000000000000999'
>>> repr(0.1000000000000999)
'0.1000000000000999'
>>> (0.01).hex()
'0x1.47ae147ae147bp-7'
我在回答当f是浮点数时,repr(f),str(f),print(f)的精度问题时,详细说明了repr
在2.7和3.1中的工作原理。
1.*1000./1000.
,可能会得到 1.0000004
或类似的结果。这是计算机存储在内存中的内容。但是,你可能不想看到那个计算结果显示为 1.0000004。所以当你打印结果时,计算机会进行四舍五入,并显示简单的 1
。但您必须知道,这不是计算机内存中实际的数值,而是您实际浮点数的一种舒适的可视化。你正在阅读的书籍不够精确。如果你真的想要看到一个浮点数的完整精度,请使用decimal
模块:
>>> import decimal
>>> decimal.Decimal(3.1415 * 2)
Decimal('6.28300000000000036237679523765109479427337646484375')
repr(a_float)
生成了17位有效数字的十进制数。虽然证明这一点很困难,但事实证明,17位有效数字足以使IEEE-754“双精度”二进制浮点数(现在几乎所有机器都使用)实现的浮点数始终满足eval(repr(a_float)) == a_float
,而16位有效数字则不够。17位有效数字不是“完全精度”,而是“足够精度,以便轮换总是起作用”。repr(a_float)
生成最短的十进制字符串,使得eval(repr(a_float)) == a_float
。这要困难得多。对于“随机”的浮点数,它可能仍然会产生17位小数,但对于人们倾向于手动输入的“简单浮点数”,它可能会产生与您输入的相同的字符串。全精度是指数字存储时保留所有小数位。由于计算机以二进制方式存储数字,这通常不会是100%准确的。
3.1415 * 2 = 6.283
,但在浮点运算中,由于四舍五入而引入了小误差。大多数显示此类计算结果的系统会自动纠正这一点,并给出您期望的结果。在Python中,当您print
一个数字时,就会发生这种情况。另一方面,repr
则按原样显示它,包括微小的误差。通常,误差非常小,不值得担心,但如果您在高精度环境中工作,则可能更喜欢避免误差的decimal
模块。__repr__
和__str__
。
当您想要对象本身的“精确”表示时,将调用第一个方法。这意味着如果您复制/粘贴__repr__
的输出,您将获得完全相同的对象。但是,这种表示并不总是人类可读的(特别是在处理更复杂的对象时),因此有__str__
。它的功能是提供对象值的文本表示,这是人类友好的。