¿Cómo fuerzo 0.0 / 0.0 para volver a cero en lugar de NaN en MIPSPro compilador de C?

StackOverflow https://stackoverflow.com/questions/2563418

  •  23-09-2019
  •  | 
  •  

Pregunta

A medida que los estados de preguntas, estoy usando el compilador C MIPSPRo, y tengo una operación que devolverá NaN para algunos conjuntos de datos donde el numerador y denom son cero. ¿Cómo puedo evitar que esto suceda?

¿Fue útil?

Solución

En los sistemas SGI con el compilador MIPSPro, se puede establecer el manejo de varias excepciones de punto flotante con gran precisión utilizando las instalaciones en sigfpe.h. Como sucede, la división de cero por cero es uno de estos casos:

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

En uso:


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

Como se puede ver, estableciendo el resultado _ZERO_DIV_ZERO cambia el resultado de la misma división. Del mismo modo que puede manejar la división regular por cero (por ejemplo, si no desea que el infinito como el resultado).

Por supuesto, nada de esto es estándar; sería más portátil para comprobar si hay NaN después de cada división y aún mejor para comprobar si hay ceros antes. C99 ofrece cierto control sobre el entorno de coma flotante en fenv.h, pero no creo que nada adecuado para esta está disponible. En cualquier caso, mi viejo MIPSPro no soporta C99.

Otros consejos

El uso de una cláusula if? También tengo curiosidad por qué te gustaría hacer caso omiso de esta imposibilidad matemática. Está seguro de su entrada no está mal / sentido en este caso?

Si no te importa la introducción de un pequeño error, se puede añadir un valor pequeño para el denominador, asumiendo que está haciendo la aritmética de coma flotante. aparentemente tiene algunos pequeños valores definidos:

DBL_MIN es el más pequeño doble

DBL_EPSILON es el doble más pequeña S.T. x + DBL_EPSILON! = x

Así que me gustaría probar

#include <float.h>
#define EPS DBL_MIN

double divModified(double num, double denom) {
    return num / (denom + EPS);
}

IEEE 754 (la especificación de punto flotante) dice que 0.0 / 0.0 es no es un número, es decir, NaN. Si usted quiere que sea otra cosa, con mucho, el mejor enfoque consiste en detectar cuando los operandos son ambos cero en una cláusula if y devolver el valor que prefiere das. Tal como esto:

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

float wonkyResult = WonkyDiv(numerator, denominator);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top