2010-08-09 5 views
32

Eventuali duplicati:
Is JavaScript’s Math broken?Perché l'aggiunta di due decimali in Javascript produce un risultato errato?

Perché JS vite questa semplice matematica?

document.write(.1 + .2) // 0.3000000000000004 
document.write(.3 + .6) // 0.8999999999999999 

Il primo esempio è maggiore del risultato corretto, mentre il secondo è inferiore. ??? !! come lo aggiusti? Devi convertire sempre i decimali in numeri interi prima di eseguire le operazioni? Devo solo preoccuparmi di aggiungere (* e/non sembrano avere lo stesso problema nei miei test)?

Ho cercato in molti posti per le risposte. Alcuni tutorial (come le forme del carrello degli acquisti) fanno finta che il problema non esista e aggiungono semplicemente valori. I guru forniscono routine complesse per varie funzioni matematiche o menzionano JS "fa un lavoro scarso" di passaggio, ma devo ancora vedere una spiegazione.

+0

Controlla le risposte a questa domanda: http://stackoverflow.com/questions/588004/is-javascripts-math-broken –

+0

Possibile duplicato di migliaia di domande su questo e su ogni singolo forum di programmazione. –

+0

Ancora ?! Abbiamo davvero bisogno di scrivere una FAQ. –

risposta

6

Questa non è una limitazione solo per JavaScript, si applica a tutti i calcoli in virgola mobile. Il problema è che 0.1 e 0.2 e 0.3 non sono esattamente rappresentabili come float javascript (o C o Java ecc.). Quindi l'output che stai vedendo è dovuto a quella inesattezza.

In particolare solo alcune somme di potenze di due sono esattamente rappresentabili. 0.5 = = 0.1b = 2^(- 1), 0.25 = 0.01b = (2^-2), 0.75 = 0.11b = (2^-1 + 2^-2) sono tutti OK. Ma 1/10 = 0,000110001100011..b può essere espresso solo come una somma infinita di poteri di 2, che a un certo punto interrompe la lingua. E 'questo taglio che sta causando questi lievi errori.

4

Da The Floating-Point Guide:

Perché non i miei numeri, come il 0.1 + 0.2 aggiungere fino a un bel giro 0.3, e invece ho un risultato strano come ,30000000000000004?

Poiché internamente, computer utilizzano un formato (binario a virgola mobile) che non possono rappresentare accuratamente un numero come 0,1, 0,2 o 0,3 affatto.

Quando il codice viene compilato o interpretato , proprio “0,1” è già arrotondato al numero più vicino in quel formato , che si traduce in un piccolo errore di arrotondamento ancor prima del calcolo succede.

Il sito contiene spiegazioni dettagliate e informazioni su come risolvere il problema (e su come decidere se si tratta di un problema nel tuo caso).

+0

Risposta più semplice. – hamzox

15

Non si tratta di un problema JS ma di un computer più generale.il numero mobile non può memorizzare correttamente tutti i numeri decimali, perché memorizzano roba in binario Ad esempio:

0.5 is store as b0.1 
but 0.1 = 1/10 so it's 1/16 + (1/10-1/16) = 1/16 + 0.0375 
0.0375 = 1/32 + (0.0375-1/32) = 1/32 + 00625 ... etc 

so in binary 0.1 is 0.00011... 

ma questo è senza fine. Tranne che il computer deve fermarsi a un certo punto. Quindi se nel nostro esempio ci fermiamo a 0.00011 abbiamo 0.09375 invece di 0.1.

Ad ogni modo il punto è, che non dipende dalla lingua ma dal computer. Ciò che dipende dalla lingua è il modo in cui visualizzi i numeri. Di solito, la lingua arrotonda i numeri a una rappresentazione accettabile. Apparentemente JS no.

Quindi quello che devi fare (il numero in memoria è abbastanza preciso) è solo per dire in qualche modo a JS di arrotondare il numero "piacevolmente" quando li converti in testo.

Si può provare la funzione sprintf che offre un controllo preciso su come visualizzare un numero.