PHP: setlocale und float Problem
Problembeschreibung
Zu Floats gibt es eine interne und eine externe Repräsentation. Intern arbeitet PHP immer mit .
Decimal. Extern kann ein Float Wert jedoch auch mit Komma angegeben sein. Bsp.: var_dump(79.95);
würde in letzterem Fall ergeben: float(79,95). Typ wäre sicher Float, würde aber als eine Kommazahl repräsentiert (externe Repräsentation) - sogar bei var_dump()
.
Problematisch ist nun, falls -wie oben zu sehen- der key LC_NUMERIC
auf eine Locale, oder ganz allgemein auf einen Wert gesetzt ist, welche die externe Repräsentation von Float auf Komma setzt. Hier in diesem
Fall auf eine DE-locale, also auf eine externe Repräsentation mit Komma: LC_NUMERIC=de_DE.UTF-8
.
Eine externe Repräsentation liegt nun wohl vor, falls eine Float Variable in PHP Methoden wie abs()
oder round()
gegeben wird.
// Auflisten aller PHP Locale Settings
echo setlocale(LC_ALL, 0) . "\n";
/* ergibt bspw.:
LC_CTYPE=en_US.UTF-8;LC_NUMERIC=de_DE.UTF-8;LC_TIME=de_DE.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=de_DE.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=de_DE.UTF-8;LC_NAME=de_DE.UTF-8;LC_ADDRESS=de_DE.UTF-8;LC_TELEPHONE=de_DE.UTF-8;LC_MEASUREMENT=de_DE.UTF-8;LC_IDENTIFICATION=de_DE.UTF-8
*/
Lösung
Der Key LC_NUMERIC
muss mit setlocale auf einen Wert gesetzt werden, welcher ermöglicht, dass die externe Repräsentation von Float in .
Decimal dargestellt wird. Es reicht hier nicht, den Key LC_ALL
zu setzen, wie Tests zeigten, sondern es muss explizit der Key LC_NUMERIC
gesetzt werden. So kann es sein, dass LC_ALL
den geänderten Wert darstellt, nicht aber jedoch LC_NUMERIC
.
In Betracht kommen Locale-Angaben von Ländern, welche Floats auch üblicherweise mit .
Decimal darstellen. USA etwa:
setlocale(LC_NUMERIC, 'en_US.UTF-8');
Empfehlung
Stattdessen kann aber auch schlicht C
angegeben werden, welches PHP anweist, den C/C++ Float-Separator Typ zu benutzen, welcher .
Decimal ist:
setlocale(LC_NUMERIC, 'C');
Links
- setlocale: http://php.net/setlocale