代码之家  ›  专栏  ›  技术社区  ›  tel

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

  •  3
  • tel  · 技术社区  · 14 年前

    我是一个相当环保的程序员,我现在正在学习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
    

    __init__ 失败,返回4.70000000000002而不是4.7。但是,如果我用“print”语句重写doctest:

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

    它运行正常。

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

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

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

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

    5 回复  |  直到 12 年前
        1
  •  4
  •   Odomontois    14 年前
    >>> point.x
    

    电话 repr str 函数,当

    >>> print point.x
    

    发生

        2
  •  3
  •   Chinmay Kanchi    14 年前

    here point.x 但如果 点.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的详细信息,请参见 here .

    编辑: -eps <= point.x - 4.7 <= eps 相当于 abs(point.x - 4.7) <= eps . 我之所以添加这一点,是因为并非所有人都熟悉Python的比较运算符链。

    既然你提到了numpy,numpy就有了一种不用自己计算eps的方法。使用 eps = numpy.finfo(float).eps 2**-53 如果你用的是numpy。注意,numpy epsilon由于某种原因大于它应该是的值,并且等于 2**-52 而不是 2**-53

        3
  •  2
  •   Gabi Purcaru BornCoder    14 年前

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

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

    在程序设计竞赛中,给出了eps和要解决的问题。 我的建议是建立一个准确的,你需要你的东西,并使用它

        4
  •  1
  •   Eric O. Lebigot    14 年前

    print 截断数字:

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

    注意,在Python的float中使用的精度:

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

    这是因为浮子 have a limited (relative) precision

        5
  •  1
  •   nisc    14 年前

    这个 comprehensive guide

    Here 是特定于Python的解释。