3

我是一个相当绿色的程序员,我现在正在学习 Python。我已经读到“Learn to Think Like a Computer Scientist”(类和方法)的第 17 章,我刚刚写了我的第一个 doctest,但以一种我真的不完全理解的方式失败了:

class Point(object):
    '''
    represents a point object.
    attributes: x, y
    '''

    def ___init___(self, x = 0, y = 0):
        '''
        >>> point = Point()
        >>> point.y
        0
        >>> point = Point(4.7, 8.2)
        >>> point.x
        4.7
        '''

        self.x = x
        self.y = y

第二个 doctest__init__失败,并返回 4.7000000000000002 而不是 4.7。但是,如果我用“打印”语句重写 doctest,如下所示:

>>> point = Point(4.7, 8.2)
>>> print point.x
4.7

它运行正确。

所以我阅读了 Python 如何存储浮点数,现在我明白了,由于十进制数的二进制表示,差异的原因是 Python 将 4.7 存储为 1 和 0 的字符串,几乎但不完全等于 4.7 .

但我不明白为什么对“point.x”的调用返回 4.7000000000000002 而对“print point.x”的调用返回 4.7。在其他什么情况下,Python 会像使用“print”一样选择舍入?这个四舍五入是如何工作的?这些尾随的重要数字是否会导致编程错误(显然,除了失败的文档测试)?不注意舍入会产生危险的歧义吗?

由于这与十进制数的二进制表示有关,我确信这实际上是一个一般的 CS 问题,而不是特定于 Python 的问题,但我现在真正需要知道的是我能做什么,特别是作为一个Python 程序员,以避免任何相关问题和/或错误侵扰。

此外,对于奖励积分,除了由“a = 4.7”之类的行激活的默认值之外,Python 是否还有其他方式可以存储浮点数?我知道有 Decimal 包,但我不完全确定它是如何工作的。老实说,所有这些动态类型的东西有时会让我感到困惑。

编辑: 我应该指定我使用的是 Python 2.6(有时我想使用 NumPy 和 Biopython)

4

5 回答 5

4
>>> point.x

调用repr用于字符串表示的函数,它比str函数持有更多的技术信息,当

>>> print point.x

发生

于 2010-08-22T17:53:27.693 回答
3

这与计算机如何存储浮点数有关。对此的详细描述是here。但是,对于您的情况,快速解决方案是不检查打印表示,point.x而是检查 ifpoint.x是否等于4.7。所以...

>>> point = Point(4.7, 8.2)
>>> point.x == 4.7
True

或更好:

>>> point = Point(4.7, 8.2)
>>> eps = 2**-53 #get epsilon for standard double precision number
>>> -eps <= point.x - 4.7 <= eps
True

哪里eps是浮点运算中舍入误差的最大值。有关 epsilon 的详细信息,请参见此处

编辑: -eps <= point.x - 4.7 <= eps相当于abs(point.x - 4.7) <= eps. 我只添加这个是因为不是每个人都熟悉 Python 的比较运算符链。

编辑 2:既然你提到了 numpy,numpy 有一种方法可以在不自己计算的情况下获取 eps。如果您使用的是 numpy ,请使用eps = numpy.finfo(float).eps而不是。2**-53请注意,由于某种原因,numpy epsilon 大于应有的大小,并且等于2**-52而不是2**-53. 我不知道为什么会这样。

于 2010-08-22T16:32:04.740 回答
2

处理浮点数时,常用方法如下:

a == b if abs(a-b) <= eps, where eps is the required precision.

在编程竞赛中,eps 与要解决的问题一起给出。我的建议是建立你的东西所需的准确性,并使用它

于 2010-08-22T16:31:30.620 回答
1

print由于截断数字,您会得到不同的行为:

In [1]: 1.23456789012334
Out[1]: 1.23456789012334 
In [2]: print 1.23456789012334
1.23456789012

注意,在 Python 的浮点数中使用的精度:

In [3]: 4.7 == 4.7000000000000002
Out[3]: True

这是因为浮点数具有有限的(相对)精度,因为它们使用有限数量的(二进制)数字来表示实数。因此,如上所述,在用最接近的浮点数近似后,给定数字的不同十进制表示实际上对于 Python 是相等的。这是浮点数的一般属性。

于 2010-08-22T16:28:46.803 回答
1

这个综合指南解释了一切。

是特定于 Python 的解释。

于 2010-08-22T17:21:14.057 回答