Come forzo 0.0 / 0.0 a restituire zero, invece di NaN in MIPSPro compilatore C?

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

  •  23-09-2019
  •  | 
  •  

Domanda

Come afferma domanda, sto usando il compilatore C MIPSPRo, e ho un operazione che tornerà NaN per alcune serie di dati in cui sia il numeratore che denom sono pari a zero. Come faccio a evitare che ciò accada?

È stato utile?

Soluzione

Su sistemi SGI con il compilatore MIPSPro, è possibile impostare la gestione di varie eccezioni in virgola mobile con precisione utilizzando le strutture in sigfpe.h. Come accade, la divisione per zero zero è uno dei casi:

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

Come si può vedere, fissando il risultato _ZERO_DIV_ZERO cambia l'esito della stessa divisione. Allo stesso modo è possibile gestire divisione regolare per zero (per esempio, se non si desidera l'infinito come il risultato).

Naturalmente, niente di tutto questo è di serie; sarebbe più portatile per controllare NaN dopo ogni divisione e ancora meglio per controllare zeri prima. C99 offre alcuni controllo sull'ambiente in virgola mobile in fenv.h, ma non credo niente di adatto per questo è disponibile. In ogni caso il mio vecchio MIPSPro non supporta C99.

Altri suggerimenti

Usa un clausola if? Anche io sono curioso di sapere perchè ci si vuole ignorare questa impossibilità matematica. Sei sicuro che il vostro ingresso non è sbagliato / senza senso in questo caso?

Se non ti dispiace l'introduzione di un piccolo errore, è possibile aggiungere un valore piccolo al denominatore, supponendo che si sta facendo aritmetica in virgola mobile. a quanto pare ha alcuni piccoli valori definiti:

DBL_MIN è il più piccolo doppio

DBL_EPSILON è il più piccolo doppio S.T. x + DBL_EPSILON! = x

Quindi vorrei provare

#include <float.h>
#define EPS DBL_MIN

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

IEEE 754 (le specifiche per la virgola mobile) dice che 0.0 / 0.0 è non un numero, cioè NaN. Se si vuole che sia qualcos'altro, di gran lunga l'approccio migliore è quello di rilevare quando gli operandi sono entrambi pari a zero in una clausola if e restituire il valore che si preferisce dare. Forse in questo modo:

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

float wonkyResult = WonkyDiv(numerator, denominator);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top