Domanda

Per rendere il problema a breve diciamo che voglio calcolare l'a / (b - c) espressione sul floats.

Per assicurarsi che il risultato è significativo, posso verificare se b e c sono in egual:

float EPS = std::numeric_limits<float>::epsilon();
if ((b - c) > EPS || (c - b) > EPS)
{
    return a / (b - c);
}

ma i miei test dimostrano che non è sufficiente a garantire sia risultati significativi né non mancando di fornire un risultato, se è possibile.

Caso 1:

a = 1.0f;
b = 0.00000003f;
c = 0.00000002f;

Risultato:. Il caso condizione non è soddisfatta, ma l'espressione produrrebbe un risultato corretto 100.000.008 (come per la precisione dei galleggianti)

Caso 2:

a = 1e33f;
b = 0.000003;
c = 0.000002;

Risultato:. La condizione if è soddisfatta, ma l'espressione non produce un significativo risultato +1.#INF00

L'ho trovato molto più affidabile per controllare il risultato, non gli argomenti:

const float INF = numeric_limits<float>::infinity();
float x = a / (b - c);
if (-INF < x && x < INF)
{
     return x;
}

Ma quello che per è l'Epsilon allora e perché tutti dicendo Epsilon è bene utilizzare?

È stato utile?

Soluzione

"è necessario utilizzare un epsilon quando si tratta di carri" è una reazione istintiva di programmatori con una comprensione superficiale di calcoli in virgola mobile, per i confronti in generale (non solo a zero).

Questo è di solito inutile perché non vi dice come ridurre al minimo la propagazione di errori di arrotondamento, ma non dice come evitare problemi di cancellazione o di assorbimento, e anche quando il problema è infatti legato al confronto dei due galleggianti, che non ti dicono quale valore di Epsilon è giusto per quello che state facendo .

Se non avete letto Ciò che ogni computer Scientist deve sapere a proposito di virgola mobile aritmetica , è un buon punto di partenza. Oltre che, se si è interessati alla precisione del risultato della divisione nel tuo esempio, è necessario stimare quanto b-c impreciso è stata fatta da precedente errori di arrotondamento, perché in effetti se b-c è piccolo, un piccolo errore assoluto corrisponde in larga errore assoluto sul risultato. Se la vostra preoccupazione è solo che la divisione non dovrebbe troppo pieno, quindi il test (il risultato) è giusto. Non v'è alcun motivo di prova per un divisore nulla con numeri in virgola mobile, basta provare per trabocco del risultato, che cattura entrambi i casi in cui il divisore è nullo e in cui il divisore è così piccola da rendere il risultato non rappresentabili con precisione.

Per quanto riguarda la propagazione di errori di arrotondamento, esiste Gli analizzatori specializzati che può aiutare a stimare, perché è una cosa noiosa da fare a mano.

Altri suggerimenti

Epsilon viene utilizzato per determinare se due numeri soggetti a errore di arrotondamento sono abbastanza vicino per essere considerato "uguale". Si noti che è meglio di prova fabs(b/c - 1) < EPS di fabs(b-c) < EPS, e ancora meglio - grazie al design di IEEE galleggia - a prova di abs(*(int*)&b - *(int*)&c) < EPSI (dove EPSI qualche piccolo intero)

.

Il tuo problema è di natura diversa, e probabilmente garantisce la verifica del risultato, piuttosto che gli ingressi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top