TDD 让我除以零。可以吗?

TDD lets me divide by zero. Is it OK?

我使用 TDD 开发了一个 class,其中一部分看起来像这样

class A
{
public:
    // methods, members, stuff

private:
    std::vector<int> vectorA;
    std::vector<int> vectorB;

    bool isAbove(double lowerBound)
    {
        double x = (double)vectorA.size() / vectorB.size();

        return x > lowerBound;
    }

    // more methods, members, stuff
};

即使在调用 isAbove()vectorB.size() 实际上是 0,所有测试也会通过 - 不会抛出异常。我是否使用调试信息构建并不重要。然而,调试显示 xlowerBound 相比是 -nan(ind)(如您所料)。

我将 VS2015 与 VS2013 (v120) 工具集一起使用。 ideone.com produces the same result.

我是否应该在计算 x 之前检查 vectorB.size() == 0,尽管(通过 TDD 过程)这不是必需的?

IEEE 754 明确定义了浮点数除以零(它几乎肯定定义了您系统上的浮点运算),它告诉我们 x 中的结果是“inf “ 价值。这将永远在“上方”lowerBound.

但是,严格来说,就 C++ 本身而言,除以零具有未定义的行为。如果你想要绝对的、可移植的安全,并且你不介意性能损失,你可以通过 if 语句来避免它。但这完全取决于你。

[C++14: 5/4]: If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. [ Note: most existing implementations of C++ ignore integer overflows. Treatment of division by zero, forming a remainder using a zero divisor, and all floating point exceptions vary among machines, and is usually adjustable by a library function. —end note ]

[C++14: 5.6/4]: [..] If the second operand of / or % is zero the behavior is undefined. [..]

浮点数除以零会在 C++ 中给出未定义的行为,因此您得到的任何结果都是正确的(至少在标准 C++ 中)。除以零时不需要生成特定值或生成任何信号。

您描述的行为与您使用 IEEE 浮点数的实现一致,其中正数除以零将得到正无穷大,负数除以零将得到负无穷大,零除以零将给出一个 NaN(非数字)[这是一种过度简化,因为 IEEE 表示允许表示正零和负零,但是您不会通过简单地转换 std::vector 的大小来得到负零至 double].

您确实需要在除以它之前测试 vectorB.size() 是否为非零。

或者,return vectorA.size() > lowerBound*vectorB.size() 给出了一个(数学上)等效的结果,没有任何除法——唯一的潜在问题是计算 lowerBound*vectorB.size() 中的溢出(这可以通过对 [ 进行范围检查来解决) =15=] and/or vectorB.size()).