tags:

views:

188

answers:

4

As the question states, I am using the MIPSPRo C compiler, and I have an operation that will return NaN for some data sets where both the numerator and denom are zero. How do I keep this from happening?

+7  A: 

Use an if clause? Also I'm curious why you'd want to ignore this mathematical impossibility. You sure your input isn't wrong/meaningless in this case?

Matti Virkkunen
+1 NaN as result of 0/0 is a standard
Andrey
I am *not* sure that it isnt meaningless, no. I am doing a finite element solver, and occaisionally around the borders, and in the "corners" of the 3d mesh will have zeros on the numerator and denominator as a result of someone specifying zeros on those edges
Derek
I am not sure how else to handle this, other than doing a check on it. The Fortran version of this compiler does have an option to allow you to specify a value for NaN, and I assume it is for this reason?
Derek
Usually the correct way would be to ignore these points. So use that if clause I suggested to check if the values are zero.
Matti Virkkunen
If we were speaking of standard C, using `if` would be the best solution, but as the asker specifies MIPSPro it just happens that this specific case is supported by it… =)
Arkku
Nicely spotted, +1. However I'm still wondering why Derek seemingly wants to "silently ignore" these cases. Usually when you hit something like this in math, there's something wrong with your input.
Matti Virkkunen
+6  A: 
Arkku
Oh, forgot to mention that you need to link with `-lfpe` as shown.
Arkku
A: 

If you don't mind introducing a small error, you can add a small value to the denominator, assuming you are doing floating point arithmetic. apparently has some small values defined:

DBL_MIN is the smallest double

DBL_EPSILON is the smallest double s.t. x+DBL_EPSILON != x

So I would try

#include <float.h>
#define EPS DBL_MIN

double divModified(double num, double denom) {
    return num / (denom + EPS);
}
Marc
denom+DBL_MIN should be good enough. If denom is 0, denom+DBL_MIN==DBL_MIN. For pretty much any other value X large enough to care about (anything larger than 2^-2047 I should guess?), X+DBL_MIN==X, so the result should be unaffected.
brone
A: 

IEEE 754 (the spec for floating point) says that 0.0/0.0 is not a number, i.e. NaN. If you want it to be anything else, by far the best approach is to detect when the operands are both zero in an if clause and return the value that you'd rather give. Perhaps like this:

#define WonkyDiv(a,b)  ((a)==0.0&&(b)==0.0 ? 0.0 : (a)/(b))

float wonkyResult = WonkyDiv(numerator, denominator);
Donal Fellows