Se ancora qualcuno raggiunge questa pagina con problemi simili in cui la sottrazione di numeri mobili causa errori o valori strani. Voglio spiegare questo problema con un po 'più di dettagli. Il colpevole sono i numeri in virgola mobile. E diversi sistemi operativi e diverse versioni dei linguaggi di programmazione possono comportarsi diversamente.
Per illustrare il problema, spiegherò perché con un semplice esempio di seguito.
Non è direttamente correlato a PHP e non è un bug. Tuttavia, ogni programmatore dovrebbe essere a conoscenza di questo problema.
Questo problema ha richiesto anche molte vite due decenni fa.
il 25 febbraio 1991 questo problema in galleggiamento il calcolo del numero in una batteria di missili MIM-104 Patriot impedito intercettare un missile Scud in entrata a Dhahran, Arabia Saudita, contribuendo alla morte di 28 soldati dal 14 Quartermaster Detachment del Stati Uniti Army.
Ma perché succede?
Il motivo è che i valori in virgola mobile rappresentano una precisione limitata. Pertanto, un valore potrebbe non avere la stessa rappresentazione di stringa dopo qualsiasi elaborazione. Inoltre, include la scrittura di un valore in virgola mobile nello script e direttamente stampandolo senza operazioni matematiche.
Basta un semplice esempio:
$a = '36';
$b = '-35.99';
echo ($a + $b);
che ci si aspetta per stampare 0.01, giusto? Ma stamperà una risposta molto strana come 0.009999999999998
Come altri numeri, i numeri in virgola mobile doppi o float vengono archiviati in memoria come una stringa di 0 e di 1.In che modo il punto variabile differisce dal numero intero è nel modo in cui interpretiamo gli 0 e gli 1 quando vogliamo guardarli. Esistono molti standard su come vengono memorizzati.
numeri a virgola mobile sono in genere confezionati in un dato computer come bit di segno, il campo esponente, e il significante o mantissa, da sinistra a destra ....
numeri decimali non sono ben rappresentati in binario a causa della mancanza di spazio sufficiente. Quindi, non puoi esprimere 1/3 esattamente come è 0.3333333 ..., giusto? Perché non possiamo rappresentare 0,01 come un numero di float binario per lo stesso motivo. 1/100 è 0,00000010100011110101110000 ..... con una ripetizione 10100011110101110000.
Se 0.01 è mantenuto in forma semplificata e sistema troncato di 01000111101011100001010 in binario, quando viene tradotto in decimale, sarebbe letto come ,0099,999 mila. ... a seconda del sistema (i computer a 64 bit offrono una precisione molto migliore rispetto a 32 bit). Il sistema operativo decide in questo caso se stamparlo come vede o come farlo in modo più leggibile. Quindi, dipende dalla macchina come vogliono rappresentarlo. Ma può essere protetto a livello di lingua con metodi diversi.
Se si formatta il risultato, echo number_format (0,009999999999998, 2); stamperà 0,01.
È perché in questo caso si indica come dovrebbe essere letto e la precisione richiesta.
Esamina "precisione" in php.ini per ulteriori modifiche a livello di PHP. Tuttavia, tieni presente che hai a che fare con * cifre significative * lì. –