Comment forcer 0,0 / 0,0 à revenir à zéro au lieu de NaN dans le compilateur C MIPSPro?

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

  •  23-09-2019
  •  | 
  •  

Question

Comme l'indique question, j'utilise le compilateur C MIPSPro, et j'ai une opération qui renverra NaN pour certains ensembles de données où le numérateur et denom sont nuls. Comment puis-je empêcher que cela se passe?

Était-ce utile?

La solution

Sur les systèmes SGI avec le compilateur MIPSPro, vous pouvez définir le traitement de diverses exceptions en virgule flottante avec une grande précision en utilisant les installations sigfpe.h. Comme il arrive, la division de zéro par zéro est un tel cas:

#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 utilisation:


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

Comme vous pouvez le voir, le résultat de la mise en _ZERO_DIV_ZERO modifie le résultat de la même division. De même, vous pouvez gérer la division par zéro régulière (par exemple si vous ne voulez pas l'infini comme le résultat).

Bien sûr, rien de tout cela est la norme; il serait plus portable pour vérifier NaN après chaque division et même préférable de vérifier les zéros avant. C99 offre un certain contrôle sur l'environnement à virgule flottante dans fenv.h, mais je ne pense pas que quoi que ce soit adapté à cette technologie est disponible. En tout cas, mon ancien MIPSPro ne supporte pas C99.

Autres conseils

Utilisez une clause if? Aussi je suis curieux de savoir pourquoi vous voudriez ignorer cette impossibilité mathématique. Tu es sûr que votre entrée est pas mal / sens dans ce cas?

Si vous ne me dérange pas l'introduction d'une petite erreur, vous pouvez ajouter une petite valeur au dénominateur, en supposant que vous faites l'arithmétique en virgule flottante. apparemment a quelques petites valeurs définies:

DBL_MIN est le plus petit à double

DBL_EPSILON est le plus petit à double S.T. x + DBL_EPSILON! = x

Je voudrais essayer

#include <float.h>
#define EPS DBL_MIN

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

IEEE 754 (pour la spécification virgule flottante) dit que 0,0 / 0,0 est pas un nombre, c.-à-NaN. Si vous voulez qu'il soit autre chose, de loin la meilleure approche est de détecter lorsque les opérandes sont tous deux à zéro dans une clause if et retourner la valeur que vous préférez donner. Peut-être comme ceci:

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

float wonkyResult = WonkyDiv(numerator, denominator);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top