Is division by zero possible in the following case due to the floating point error in the subtraction?
float x, y, z;
...
if (y != 1.0)
z = x / (y - 1.0);
In other words, is the following any safer?
float divisor = y - 1.0;
if (divisor != 0.0)
z = x / divisor;
Dividing a number by Zero is a mathematical error (not defined) and we can use exception handling to gracefully overcome such operations. If you write a code without using exception handling then the output of division by zero will be shown as infinity which cannot be further processed.
In languages like C, C++ etc. division by zero invokes undefined behaviour.
Microsoft Excel shows the #DIV/0! error when a number is divided by zero (0). It happens when you enter a simple formula like =5/0, or when a formula refers to a cell that has 0 or is blank, as shown in this picture.
The reason, in short, is that whatever we may answer, we will then have to agree that that answer times 0 equals to 1, and that cannot be true, because anything times 0 is 0.
Assuming IEEE-754 floating-point, they are equivalent.
It is a basic theorem of FP arithmetic that for finite x and y, x - y == 0 if and only if x == y, assuming gradual underflow.
If subnormal results are flushed to zero (instead of gradual underflow), this theorem holds only if the result x - y is normal. Because 1.0 is well scaled, y - 1.0
is never subnormal, and so y - 1.0
is zero if and only if y is exactly 1.0, regardless of how underflow are handled.
C++ doesn't guarantee IEEE-754, of course, but the theorem is true for most "reasonable" floating-point systems.
This will prevent you from dividing by exactly zero, however that does not mean still won't end up with +/-inf
as a result. The denominator could still be small enough so that the answer is not representable with a double
and you will end up with an 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
is non-zero, but it is so small that large
exceeds the range of double
and is inf
.
There is no difference between the two code snippets () - in fact, the optimizer could even optimize both fragments to the same binary code, assuming that there are no further uses of the divisor
variable.
Note, however, that division by a floating point zero 0.0
does not result in a run-time error, but produces an inf
or -inf
instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With