Python中数字值的陷阱;“有多深?”;

Python中数字值的陷阱;“有多深?”;,python,binary,floating-point,ambiguity,Python,Binary,Floating Point,Ambiguity,我是一个相当环保的程序员,现在正在学习Python。我读到了《学会像计算机科学家一样思考》(课程和方法)第17章,我刚刚写了我的第一个博士测试,但以一种我真的不完全理解的方式失败了: class Point(object): ''' represents a point object. attributes: x, y ''' def ___init___(self, x = 0, y = 0): ''' >>

我是一个相当环保的程序员,现在正在学习Python。我读到了《学会像计算机科学家一样思考》(课程和方法)第17章,我刚刚写了我的第一个博士测试,但以一种我真的不完全理解的方式失败了:

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
\uuuu init\uuuu
的第二个doctest失败,返回4.70000000000002而不是4.7。但是,如果我用“print”语句重写doctest,如下所示:

>>> point = Point(4.7, 8.2)
>>> print point.x
4.7
它运行正常

因此,我阅读了Python如何存储浮动,现在我了解到,由于十进制数的二进制表示,产生差异的原因是Python将4.7存储为1和0组成的字符串,几乎等于但不完全等于4.7

但我不明白的是,为什么调用“point.x”返回4.70000000000002,调用“print point.x”返回4.7。在其他什么情况下,Python会选择像“print”一样进行取整?这个舍入是如何工作的?这些尾随的有效数字会导致编程错误吗(显然,除了失败的doctest之外)?不注意四舍五入会造成危险的歧义吗

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

另外,对于额外的积分,除了由“a=4.7”这样的行激活的默认值之外,Python还有其他方法可以存储浮点数吗?我知道有十进制软件包,但我不完全确定它是如何工作的。老实说,所有这些动态打字的东西有时让我感到困惑

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

您会得到不同的行为,因为
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来说,给定数字的不同十进制表示形式在用最接近的浮点近似后实际上是相等的。这是浮点数的一般属性。

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


a==b如果abs(a-b)这与计算机存储浮点数的方式有关。详细描述如下。但是,对于您的情况,快速解决方案不是检查
point.x
的打印表示,而是检查
point.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
>点=点(4.7,8.2)
>>>eps=2**-53#获取标准双精度数字的ε
>>>-eps这解释了一切

这些都是特定于Python的解释

>>> point.x
调用
repr
函数,该函数用于保存比
str
函数更多的技术信息的字符串表示,该函数在

>>> print point.x

发生

最近的Python版本(2.7和3.1)将显示4.7,即使没有打印
。但潜在的误差(由于浮点不精确)仍然存在。机器ε是相对误差的界。您不能像以前那样使用它,因为对于远离零的值,绝对误差会更大。在这种特殊情况下,
point.x-4.7
无论如何都会给出精确的0。感谢您回答我应该问的问题