1

我正在做如何像计算机科学家一样思考的第 5 章中的练习,并试图解决第三个练习:

编写一个函数slope(x1, y1, x2, y2),返回通过点 (x1, y1) 和 (x2, y2) 的直线的斜率。确保您的实现slope可以通过以下文档测试:

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()来获取绝对值,但是,如果我确实有应该得出负数的参数,它就行不通了。

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

4

1 回答 1

2

您可以通过交换代码中的顺序和代码来编写一个版本,slope()该版本对该文档测试中的参数返回正数:0.0y1 - y2x1 - 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

......但在不太重要的文档测试之外,因为0.0-0.0在定义上是相等的。但是,如果您想确保始终返回一个正零,您可以将零添加到您的返回值:

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 浮点标准规定它必须:

当两个符号相反的操作数之和(或两个符号相同的操作数之差)恰好为零时,该和(或差)的符号在除roundTowardNegative之外的所有舍入方向属性中应为+0;在该属性下,精确零和(或差)的符号应为 -0。然而,即使 x 为零,x + x = x - (-x) 仍保留与 x 相同的符号。

— IEEE 754,第 6.3 节

有关浮点算术中带符号零的更多信息,请参阅 每个计算机科学家应该了解的浮点算术知识

于 2018-03-11T23:24:32.653 回答