简体   繁体   中英

TDD lets me divide by zero. Is it OK?

I used TDD to develop a class that in one part looks like this

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
};

All tests pass even if vectorB.size() is actually 0 when isAbove() is called - no exception thrown. It doesn't matter if I build with debug infos or not. However debugging showed that x is -nan(ind) when compared to lowerBound (as you may have expected).

I use VS2015 with VS2013 (v120) toolset. ideone.com produces the same result .

Should I check for vectorB.size() == 0 before calculating x although (by the process of TDD) this isn't needed?

Floating-point division by zero is well-defined by IEEE 754 (which almost certainly defines floating-point operations on your system), which tells us that the result, in x , is the "inf" value. This will always be "above" lowerBound .

However, strictly speaking, in terms of C++ itself, division by zero has undefined behaviour. If you want to be absolutely, portably safe, and you don't mind the performance penalty, you can avoid it via an if statement. But that's entirely up to you.

[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. [..]

Floating point division by zero gives undefined behaviour in C++, so any result you get is correct (at least, within standard C++). There is no requirement that a particular value be produced, or that any signal be generated, on division by zero.

The behaviour you describe is consistent with your implementation using IEEE floating point, in which division of a positive by zero will give a positive infinity, division of a negative by zero will give a negative infinity, and division of zero by zero will give a NaN (non-a-number) [this is an over-simplification as IEEE representation allows representation of positive and negative zeros, but you will not get a negative zero by simply converting a std::vector 's size to double ].

You really need to test that vectorB.size() is non-zero before dividing by it.

Alternatively, return vectorA.size() > lowerBound*vectorB.size() which gives a (mathematically) equivalent result without any division - the only potential issue with that is overflow in computing lowerBound*vectorB.size() (which can be addressed by doing range checking on lowerBound and/or vectorB.size() ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM