Numeri floating point

I valori floating point (anche conosciuti come "float", "double", o "numeri reali") possono essere specificati utilizzando una delle seguenti sintassi:

<?php
$a
= 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // a partire da PHP 7.4.0
?>

Formalmente a partire da PHP 7.4.0 (in precedenza, i trattini bassi non erano consentiti):

LNUM          [0-9]+(_[0-9]+)*
DNUM          ({LNUM}?"."{LNUM}) | ({LNUM}"."{LNUM}?)
EXPONENT_DNUM (({LNUM} | {DNUM}) [eE][+-]? {LNUM})

La dimensione di una variabile float dipende dalla piattaforma in uso, sebbene un massimo di circa 1.8e308 con una precisione di circa 14 cifre decimali sia il valore comune (il formato a 64 bit IEEE).

Avviso

Precisione di un valore floating point

I numeri floating point hanno una precisione limitata. Nonostante questa dipenda dal sistema in uso. PHP tipicamente utilizza il formato IEEE 754 double-precision, il quale pone un errore relativo massimo causato dall'arrotondamento nell'ordine di 1.11e-16. Operazioni aritmetiche non elementari possono restituire un errore maggiore e, di conseguenza, la propagazione dell'errore deve essere considerata quando più operazioni vengono eseguite in successione.

In più, alcuni numeri razionali che sono esattamente rappresentabili come numeri floating point in base 10, ad esempio 0.1 o 0.7), non hanno, al contrario, una rappresentazione come numeri floating point in base 2, la quale viene utilizzata internamente dal sistema, indipendentemente dalla dimensione della mantissa. Dunque, questi non possono essere convertiti nella loro controparte binaria interna senza una piccola perdita di precisione. Ciò può portare a risultati confusionari: per esempio, floor((0.1+0.7)*10) solitamente ritornerà come risultato 7 invece di 8, in quanto la sua rappresentazione interna sarà qualcosa di simile a 7.9999999999999991118....

Perciò non fate mai affidamento sui risultati numerici decimali sino all'ultima cifra e non comparate numeri floating point direttamente per uguaglianza. Se è necessaria una maggior precisione, sono disponibili le funzioni matematiche con precisione arbitraria e le funzioni gmp.

Per una "semplice" spiegazione, vedere la » guida per floating point, la quale è anche intitolata "Why don’t my numbers add up?"

Conversione a float

Da stringhe

Se la stringa è numerica o inizia con un numero, verrà risolta nel valore float corrispondente, altrimenti verrà convertita in zero (0).

Da altri tipi

Per i valori di altri tipi, la conversione viene eseguita convertendo il valore prima in int e poi in float. Vedere Conversione in numero intero per ulteriori informazioni.

Nota:

Poiché alcuni tipi hanno un comportamento indefinito durante la conversione in int, lo stesso vale durante la conversione in float.

Comparare float

Come fatto notare nell'esempio sopra, comparare valori floating point per uguaglianza potrebbe risultare problematico a causa della loro rappresentazione interna. Tuttavia esistono dei metodi per comparare dei valori floating point che aggirano queste limitazioni.

Per confrontare valori floating point per uguaglianza viene scelto un limite superiore all'errore relativo creato dall'arrotondamento. Questo valore è conosciuto come la macchina epsilon, o unità roundoff, ed è la più piccola differenza accettabile nel calcolo.

$a e $b sono uguali per 5 cifre di precisione.

<?php
$a
= 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;

if(
abs($a-$b) < $epsilon) {
echo
"true";
}
?>

NaN

Alcune operazioni possono ritornare un valore rappresentato dalla costante NAN. Questo risultato rappresenta un valore indefinito o non presentabile nei calcoli di numeri floating point. Qualsiasi comparazione per uguaglianza o per identicità di questo valore con qualsiasi altro, incluso sé stesso, risulterà false.

Poiché NAN rappresenta un qualsiasi numero di differenti valori, NAN non dovrebbe essere comparato ad altri valori, incluso se stesso, e dovrebbe invece essere verificato tramite la funzione is_nan().