PHP: setlocale und float Problem
2013-12-10

PHP,Locale,DE

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

Related


Comment++

E-Mail Adresse wird nicht veröffentlicht.
E-mail address will not be published.