浮点数字

时间:2013-12-09 15:12:48

标签: python floating-point

所以我正在阅读这个名为“学习Python第四版”的PDF教程。现在我找到了一个我不理解的部分,因为我几乎是Python的初学者。我在谈论这一部分:

enter image description here

现在我没有得到第一个例子的解释。它确实说: 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程序员很容易解释,但我似乎没有得到它。

7 个答案:

答案 0 :(得分:13)

这不是Python问题,而是浮点数性质的问题。事实证明,计算机不能代表数字。谁知道?

如果你有时间,我建议你阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic

现在,对于实际的Python方面,每个对象都有一个名为__str__的方法和一个名为__repr__的方法。这些应该产生在各种情况下显示的字符串。如果您在任何对象上使用内置reprstr函数,或者在字符串格式中使用"%r""%s"格式,则会看到这些内容。在交互式提示符下评估某些内容时,默认情况下会获得repr。当您将某些内容传递给print时,默认情况下会获得str

浮点数对象的__repr__定义为以最大精度(至少可以达到十进制)表示它们,而__str__的定义方式是{{1}}往往看起来更像你想要向用户展示的东西。用户不想知道浮点数不是实数,因此它不会向它们显示额外的精度。

答案 1 :(得分:4)

strrepr之间有什么区别”甚至“完全精确意味着什么”的答案取决于Python版本。


repr(f)的行为在3.1和 2.7 中发生了变化。

  • 在2.7(包括Python 3.0)之前,repr(f)最多会提供17位有效数字,就好像使用%17g格式化一样。 IEEE-754浮点值具有53个有效二进制数字,大约为16个十进制数字。 17位有效数字保证每个二进制值产生不同的十进制值。

  • 在Pythons 2.73.1中,repr(f)在保持精确度的同时变得人性化:

  

repr() float的{​​{1}}在很多情况下更短:它现在基于最短的十进制字符串,可以保证回到x。与之前版本的Python一样,保证x恢复float(repr(x))


在Python 3.2中改变了x的行为:


以下示例演示了str(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 (在Python 3.2之前)的旧行为是将值舍入为12位有效数字,丢失信息:

str

自Python 3.2以来的新行为表现得像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中的浮点数表示为IEEE-754双精度;一个数字需要64位,其中1位保留用于符号,10位用于指数,53位用于尾数(实际数字)。

许多值(例如π 1/3 )无法准确表示为IEEE-754二进制浮点值。即使是 0.01 这样的常见数字也无法准确表示。

Python 3 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' 的方法float将数字转换为十六进制表示,可用于轻松查看问题:

hex()

因此,作为十六进制,数字0.01将以二进制近似为 1.47AE147AE147A4147AE ...·2 -7 ;舍入到53个有效位中最接近的数字,表示为 1.47AE147AE147B·2 -7


在我对问题Precision of repr(f), str(f), print(f) when f is float的回答中,我已经写了一些关于>>> (0.01).hex() '0x1.47ae147ae147bp-7' 如何在2.7,3.1中工作的更详细的细节。

答案 2 :(得分:3)

基本上,计算机的浮点计算存在舍入误差。因此,如果您执行1.*1000./1000.,最终可能会遇到1.0000004或类似内容。这是计算机存储在内存中的内容。但是,您可能不希望看到1.0000004作为该计算的结果。因此,当您打印结果时,计算机会进行舍入,您只需1。但是你必须知道它不是计算机内存中的真正价值 - 它只是对你的实际浮点数的一种舒适的可视化。

答案 3 :(得分:2)

完全精确,它们表示数字存储为的所有小数位数。由于数字如何存储在计算机上(二进制),这通常不是100%准确。

答案 4 :(得分:2)

你正在读的书是不精确的。如果您真的希望看到浮点数达到完全精度,请使用decimal模块:

>>> import decimal
>>> decimal.Decimal(3.1415 * 2)
Decimal('6.28300000000000036237679523765109479427337646484375')

每个(有限的)二进制浮点数可以精确地表示为(有限的)十进制浮点数。反之亦然 - 实际上,大多数十进制浮点数不能完全表示为(有限)二进制浮点数。

旧版CPython的不同之处在于repr(a_float)产生了17位有效小数。虽然证明这很困难,但事实证明,17个有效十进制数字足以使eval(repr(a_float)) == a_float对于实现为IEEE-754“双精度”二进制浮点(几乎所有机器现在都使用)的浮点数始终为真 - 和16有效十进制数字是不够的。 17是“全精度”,它“足够的精度使得往返总是有效”。

在当前版本的CPython中,repr(a_float)生成最短的十进制字符串,使eval(repr(a_float)) == a_float。要做到这一点要困难得多。对于“随机”浮动,它可能仍然会生成17个十进制数字,但对于“简单浮动”,人们倾向于手动输入,它可能会生成您键入的相同字符串。

答案 5 :(得分:1)

这可能是一个相当令人困惑的问题!数学3.1415 * 2 = 6.283,但在浮点运算中,由于四舍五入而引入了小错误。大多数显示此类计算结果的系统会自动对此进行校正,并为您提供所期望的结果。在python中,当你print一个数字时会发生这种情况。另一方面,repr显示它的原样,包括微小的错误。通常错误是如此之小以至于不值得担心,但如果您在高精度环境中工作,那么您可能更喜欢decimal模块来避免错误。

答案 6 :(得分:0)

python类应该定义两种特殊方法:__repr____str__。 当您想要对象本身的“精确”表示时,会调用第一个。这意味着如果您复制/粘贴__repr__的输出,您将获得完全相同的对象。然而,这种表示并不总是人类可读的(特别是在处理更复杂的对象时),因此存在__str__。它的功能是给出对象价值的文本表示,这是人类友好的。