Gleitkommazahlen
Gleitkommazahlen (auch als "floats", "doubles" oder "reelle Zahlen" bezeichnet) können anhand einer der folgenden Schreibweisen bezeichnet werden:
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // von PHP 7.4.0 an
?>
Formell von PHP 7.4.0 an (zuvor waren Unterstriche nicht erlaubt):
LNUM [0-9]+(_[0-9]+)* DNUM ([0-9]*(_[0-9]+)*[\.]) | ([\.][0-9]*(_[0-9]+)*) EXPONENT_DNUM (( | ) [eE][+-]? )
Die Größe einer Gleitkommazahl ist plattformabhängig, ein Maximalwert von circa 1.8e308 mit einer Präzision von ungefähr 14 Dezimal-Nachkommastellen ist jedoch ein üblicher Wert (64-Bit IEEE-Format).
Genauigkeit von Gleitkommazahlen
Gleitkommazahlen haben eine begrenzte Präzision. Obgleich dies vom System abhängig ist, verwendet PHP üblicherweise das IEEE 754 Double Precision Format, welches einen maximalen relativen Rundungsfehler in einer Größenordnung en 1.11e-16 ergibt. Nicht-Elementare arithmetische Operationen können jedoch größere Fehler hervorgerufen und natürlich muss eine Fortpflanzung des Fehlers berücksichtigt werden, wenn mehrere Operationen zusammengesetzt werden.
Außerdem gibt es rationale Zahlen die zur Basis 10 als Gleitkommazahlen
exakt dargestellt werden können, beispielsweise 0.1
or
0.7
, für die es aber keine exakte Repräsentation als
Gleitkommazahlen zur Basis 2 gibt, welche intern aber unabhängig von der
Größe der Mantisse verwendet wird. Daher können Sie nicht ohne einen
geringen Präzisionsverlust in ihre intern binäre Darstellung umgewandelt
werden. Dies kann zu verwirrenden Ergebnissen führen:
floor((0.1+0.7)*10)
wird üblicherweise
7
ergeben statt des erwarteten Ergebnisses von
8
, da die interne Repräsentation etwas ist wie
7.9999999999999991118...
.
Man sollte sich daher niemals bis zur letzten Nachkommastelle auf Gleitkommazahlen verlassen und Gleitkommazahlen niemals direkt auf Gleichheit prüfen. Wenn eine höhere Präzision notwendig ist, stehen die Mathematikfunktionen mit beliebiger Präzision und die gmp-Funktionen zur Verfügung.
Für eine "einfache" Erklärung, steht der Ratgeber » Floating Point Guide zur Verfügung, welche auch den Titel hat "Why don’t my numbers add up?"
Umwandlung in float
Von Strings
Wenn der String
numerisch ist oder
numerisch beginnt, wird er in den entsprechenden entsprechenden
Gleitkommawert umgewandelt, andernfalls wird er in Null
(0
) umgewandelt.
Von anderen Typen
Werte aller anderen Typen werden umgewandelt, indem der Wert zuerst in den Typ int umgewandelt wird und dieser anschließend zu float. Weitere Informationen findet man unter Umwandlung in Integer.
Hinweis:
Da bestimmte Typen ein undefiniertes Verhalten bei der Umwandlung in int haben, ist dies auch bei der Umwandlung in float der Fall.
Gleitkommazahlen vergleichen
Wie in der obigen Warnung bereits dargestellt, ist es problematisch Gleitkommazahlen auf Gleichheit zu überprüfen, aufgrund ihrer internen Darstellungsart. Es gibt allerdings Wege, diese Vergleiche von Gleitkommazahlen anzustellen, die diese Beschränkungen umgehen.
Um Gleitkommazahlen auf Gleichheit zu prüfen, wird eine obere Schranke für den Rundungsfehler verwendet. Dieser Wert ist bekannt als Maschinengenauigkeit Epsilon und stellt die kleinste annehmbare Differenz in der Berechnung dar.
$a und $b sind bis auf 5 Nachkommastellen gleich.
<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if(abs($a-$b) < $epsilon) {
echo "true";
}
?>
NaN
Einige numerische Operationen können einen Wert ergeben, der durch die
Konstante NAN
dargestellt wird. Dieses Ergebnis
stellt einen undefinierten oder nicht darstellbaren Wert in den
Fließkommaberechnungen dar. Jeder strikte oder nicht strikte Vergleich
dieses Werts mit jedem beliebigen anderen Wert, inklusive sich selbst, nur
nicht true
, wird ein Ergebnis von false
hervorbringen.
Da NAN
eine beliebige Anzahl von anderen Werten
darstellen kann, sollte NAN
nicht mit anderen Werten,
einschließlich sich selbst, verglichen werden. Stattdessen sollte zur
Prüfung is_nan() verwendet werden.