2015-05-14 5 views
13

Capisco che il punto in virgola mobile abbia errori di arrotondamento, ma mi chiedo se ci sono alcune situazioni in cui l'errore non si applica, come la moltiplicazione per zero.La moltiplicazione del punto mobile per zero è garantita per produrre zero?

zero volte un numero = zero per tutti i punti mobili?

+3

Oltre ai valori speciali come NaN, Infinity o -Infinity, è corretto assumere che qualsiasi numero normale moltiplicato per lo zero esatto produce esattamente zero. –

risposta

19

Falso:

0f * NAN == NAN 
0f * INFINITY == NAN 

e ...

0f * -1f == -0f (negative 0f), with 0f == -0f :-) 

(su Intel, VC++, e, probabilmente, su qualsiasi piattaforma che utilizza IEEE 754-1985 punti flottanti)

Esempio su ideone (che utilizza GCC su una piattaforma compatibile Intel probabilmente)

+4

Sì, questo è garantito su qualsiasi sistema conforme a IEEE-754 (ma per essere perfettamente chiaro: -0 è ancora "zero"). –

+2

@StephenCanon È ancora '" 0 "' nel senso che '0f == -0f', ma per esempio se si moltiplica' -0f * INFINITY' e si stampa il risultato, si ottiene '-NaN', quindi è ancora '0' ma il suo segno può essere usato/estratto. http://ideone.com/L6MQlQ – xanatos

+2

Il signbit di un NaN non ha significato, quindi in realtà non esiste qualcosa come '-NaN', né' -0 * inf' garantisce la produzione di "' -NaN' "(potrebbe produrre qualsiasi valore NaN silenzioso). Il signbit di '-0' può essere estratto con altri mezzi, comunque. –

2

Inoltre a @xanatos risposta bene, prendere in considerazione alcuni dei PO middle-of-the-post preoccupazioni:

mi chiedo se ci sono alcune situazioni in cui il (arrotondamento) Errore non si applica

candidati includono some_double_y = some_double_x * 1.0 e some_double_y = some_double_x + 0.0 non possono mai incorrere in un errore di arrotondamento.

Tuttavia anche questi sono sospetti a causa di un compilatore può valutare double a precisione superiore considerando la FLT_EVAL_METHOD == 2 dove "valutare tutte le operazioni e le costanti alla gamma e la precisione del tipo long double". In tal caso, un valore intermedio some_double_x può esistere come long double diverso da un valore double apparente di 0.0 o 1.0.

+0

Non sono sicuro di seguire "un intermedio some_double_x può esistere come un doppio lungo che differisce da un doppio valore apparente di 0.0 o 1.0". Se some_double_x è una variabile doppia, I capire questo significa che potrebbe essere lanciato per un lungo doppio, aggiunto zero/moltiplicato per uno (che dovrebbe essere no-op, giusto?), e poi lanciato nuovamente per raddoppiare. la precisione e il dorso potrebbero causare errori di arrotondamento? – Jaan

+0

@Jaan Non è un problema di _casting_ o _rounding_. Con 'double x = some_small_double(); if (x/1.0e300) ... 'può o non può prendere il percorso' if() '. 'X/1.0e300' calcolato usando la matematica' doppia' è certamente +/- 0.0. 'x/1.0e300' calcolato usando 'lunga double' math (anche se gli operandi sono entrambi' double') potrebbe essere un numero diverso da zero. – chux

+0

@Jaan "ha aggiunto zero/moltiplicato per uno (che dovrebbe essere no-op, giusto?)" -> Non sempre. '-0.0' differisce dall'aggiunta dello zero. '-0.0 + 0.0' di solito ha una somma di' + 0.0'. [A volte] (https://stackoverflow.com/q/25332133/2410359) questa differenza è importante. I _think_ '* 1' è di solito un no-op, ma se no-op, perché codificarlo? – chux