Division with zero prophylaxis: does checking the expression of the divisor not lead to zero or verify that the divisor is not equal to zero?

Is division by zero possible in the following case due to a floating point error in subtraction?

float x, y, z; ... if (y != 1.0) z = x / (y - 1.0); 

In other words, is it safer?

 float divisor = y - 1.0; if (divisor != 0.0) z = x / divisor; 
+7
source share
3 answers

This will not allow you to divide exactly by zero, however, this does not mean that in the end the result will not be +/-inf . The denominator can still be small enough so that the answer is not represented using double , and you get inf . For example:

 #include <iostream> #include <limits> int main(int argc, char const *argv[]) { double small = std::numeric_limits<double>::epsilon(); double large = std::numeric_limits<double>::max() / small; std::cout << "small: " << small << std::endl; std::cout << "large: " << large << std::endl; return 0; } 

In this program, small nonzero, but it is so small that large exceeds the double range and is inf .

+5
source

Assuming IEEE-754 floating point, they are equivalent.

This is the main theorem of FP-arithmetic that for finite x and y, x - y == 0 if and only if x == y, assuming a gradual overflow.

If the subnormal results are reset to zero (instead of a gradual lower flow), this theorem is true only if the result x - y is normal. Since 1.0 scales well, y - 1.0 never subnormal, and so y - 1.0 is zero if and only if y is 1.0, regardless of how underflow is handled.

C ++ does not guarantee IEEE-754, of course, but the theorem is true for most "smart" floating point systems.

+6
source

There is no difference between the two code snippets () - in fact, the optimizer can even optimize both snippets to the same binary code, assuming that there is no longer any use of the divisor variable.

Note, however, that dividing by zero with a floating point of 0.0 does not result in a run-time error, but instead creates an inf or -inf .

+2
source

All Articles