2010-10-29 16 views
9

Qualcuno può spiegare perché moltiplicare per 100 qui dà un risultato meno accurato ma moltiplicando per 10 due volte si ottiene un risultato più accurato?ruby ​​errori in virgola mobile

± % sc 
Loading development environment (Rails 3.0.1) 
>> 129.95 * 100 
12994.999999999998 
>> 129.95*10 
1299.5 
>> 129.95*10*10 
12995.0 
+1

Molto probabilmente a causa della rappresentazione binaria di numeri in virgola mobile. Non si può scrivere estesamente 129,95 nella base 2 presumo. –

+10

Link obbligatorio: [Ciò che ogni scienziato informatico dovrebbe sapere circa l'aritmetica virgola mobile] (http://docs.sun.com/source/806-3568/ncg_goldberg.html) –

+0

Eventuali indizi sul perché questo NON sta accadendo per me? Sto cercando di dimostrarlo e inserisco 129.95 * 100 come sopra in IRB e ottengo inaspettatamente la risposta corretta. – Joel

risposta

22

Se fate i calcoli a mano in binario doppia precisione, che è limitato a 53 bit significativi, si vedrà quello che sta succedendo:

129,95 = 1,0000001111100110011001100110011001100110011001100110 x 2^7

129,95 * 100 = 1.1001011000010111111111111111111111111111111111111111011 x 2^13

Questo è lungo 56 bit significativi, in modo arrotondato a 53 bit è

1,10010110000101111111111111111111111111111111111111 11 x 2^13, pari

12994,999999999998181010596454143524169921875

Ora 129,95 * 10 = 1.01000100110111111111111111111111111111111111111111111 x 2^10

Questo è 54 bit significativi lunghe, in modo arrotondato a 53 bit è 1,01000100111 x 2^10 = 1299,5

Ora 1.299,5 * 10 = 1,1001011000011 x 2^13 = 12995.

3

Prima di tutto: si guarda la rappresentazione della stringa del risultato, non il risultato stesso. Se si in realtà desidera confrontare i due risultati, è necessario formattare entrambi i risultati in modo esplicito, utilizzando String#% e si dovrebbero formattare entrambi i risultati allo stesso modo.

In secondo luogo, questo è il modo in cui funzionano i numeri in virgola mobile. Sono inesatti, sono finiti e sono binari. Tutti e tre significano che si ottengono errori di arrotondamento, che in genere appaiono del tutto casuali, a meno che non si abbia memorizzato l'intero IEEE754 e si possa recitarlo all'indietro nel sonno.

2

Non esiste un numero in virgola mobile esattamente uguale a 129.95. Quindi la tua lingua usa un valore che è vicino ad esso. Quando quel valore viene moltiplicato per 100, il risultato è vicino a 12995, ma non è uguale a 12995. (Non è esattamente uguale a 100 volte il valore originale usato al posto di 129.95). Quindi il tuo interprete stampa un numero decimale che è vicino (ma non uguale a) al valore di 129.95 * 100 e che mostra che non è esattamente 12995. Si dà anche il caso che il risultato 129.95 * 10 sia esattamente uguale a 1299,5. Questa è principalmente fortuna.

La linea di fondo è, non aspettatevi mai l'uguaglianza da qualsiasi aritmetica in virgola mobile, solo "vicinanza".