浮点除法返回-0.0而不是0.0

时间:2018-03-11 21:41:44

标签: python python-2.7 floating-point return-value negative-zero

我正在进行How to Think Like a Computer Scientist第5章的练习,并试图解决第3次练习:

  

写一个返回斜率的函数slope(x1, y1, x2, y2)   穿过点(x1,y1)和(x2,y2)。一定要你的   slope的实现可以通过以下doctests:

def slope(x1, y1, x2, y2):
    """
      >>> slope(5, 3, 4, 2)
      1.0
      >>> slope(1, 2, 3, 2)
      0.0
      >>> slope(1, 2, 3, 3)
      0.5
      >>> slope(2, 4, 1, 2)
      2.0
    """

这是我提出的代码:

def slope(x1, y1, x2, y2):
    """
        >>> slope(5, 3, 4, 2)
        1.0
        >>> slope(1, 2, 3, 2)
        0.0
    """
    sy = float(y1 - y2)
    sx = float(x1 - x2)
    return sy / sx

在第二次doctest上我得到-0.0而不是0.0 ...这令人困惑,因为我不知道-0.0是一件事。我知道我可以使用abs()获取绝对值,但是如果我确实有参数应该是负数,那么它就不会起作用。

还知道我可以在结果上设置一个条件,因此它使用绝对值或不是,但我想知道我是否只是在这里做错了。

1 个答案:

答案 0 :(得分:2)

您可以通过在代码中交换slope()0.0的顺序来编写y1 - y2版本,为该doctest中的参数返回正数x1 - x2

def slope(x1, y1, x2, y2):
    """
        >>> slope(5, 3, 4, 2)
        1.0
        >>> slope(1, 2, 3, 2)
        0.0
    """
    sy = float(y2 - y1)
    sx = float(x2 - x1)
    return sy / sx

>>> slope(1, 2, 3, 2)
0.0

如果争论相反,你仍会得到-0.0

>>> slope(3, 2, 1, 2)
-0.0

...但在doctests之外不太重要,因为0.0-0.0在定义上是相同的。但是,如果您想确保始终返回正零,则只需add zero即可获得返回值:

def slope(x1, y1, x2, y2):
    """
        >>> slope(5, 3, 4, 2)
        1.0
        >>> slope(1, 2, 3, 2)
        0.0
    """
    sy = float(y2 - y1)
    sx = float(x2 - x1)
    return sy / sx + 0  # prevent -0.0

>>> slope(1, 2, 3, 2)
0.0
>>> slope(3, 2, 1, 2)
0.0

"添加正零"技巧是任意的,本质上是神奇的行为,并且只是因为IEEE 754浮点标准说它必须:

  

当具有相反符号的两个操作数的总和(或具有相同符号的两个操作数的差异)是   正好为零,除非是所有舍入方向属性,该和(或差)的符号应为+0   roundTowardNegative;在该属性下,精确零和(或差)的符号应为-0。   但是,即使x为零,x + x = x - ( - x)也保持与x相同的符号。

     

- IEEE 754,第6.3节

有关浮点运算中有符号零的更多信息,请参见What Every Computer Scientist Should Know About Floating-Point Arithmetic