Question

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?

Was it helpful?

Solution

On SGI systems with the MIPSPro compiler, you can set the handling of various floating point exceptions with great precision using the facilities in sigfpe.h. As it happens, the division of zero by zero is one such case:

#include <stdio.h>
#include <sigfpe.h>

int main (void) {
    float x = 0.0f;
    (void) printf("default %f / %f = %f\n", x, x, (x / x));
    invalidop_results_[_ZERO_DIV_ZERO] = _ZERO;
    handle_sigfpes(_ON, _EN_INVALID, 0, 0, 0);
    (void) printf("handled %f / %f = %f\n", x, x, (x / x));
    return 0;
}

In use:


arkku@seven:~/test$ cc -version
MIPSpro Compilers: Version 7.3.1.3m
arkku@seven:~/test$ cc -o sigfpe sigfpe.c -lfpe
arkku@seven:~/test$ ./sigfpe
default 0.000000 / 0.000000 = nan0x7ffffe00
handled 0.000000 / 0.000000 = 0.000000

As you can see, setting the _ZERO_DIV_ZERO result changes the outcome of the same division. Likewise you can handle regular division by zero (e.g. if you don't want infinity as the result).

Of course, none of this is standard; it would be more portable to check for NaN after each division and even better to check for zeros before. C99 offers some control over the floating point environment in fenv.h, but I don't think anything suitable for this is available. In any case my old MIPSPro doesn't support C99.

OTHER TIPS

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?

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

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);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top