Bug #53711 [Com]: Casting float->string->float with locale

From: Date: Sun, 16 Mar 2014 20:49:14 +0000
Subject: Bug #53711 [Com]: Casting float->string->float with locale
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-184804@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=53711&edit=1 ID: 53711 Comment by: marc at lithia dot nl Reported by: luke at cywh dot com Summary: Casting float->string->float with locale Status: Wont fix Type: Bug Package: Math related PHP Version: 5.2.17 Block user comment: N Private report: N New Comment: This is a very serious bug that appears in almost any web application framework written in php. It *can* be solved without breaking backwards compatibility. PHP got rid of magic quotes as well didn't it? Create an ini setting, like 'locale_aware_casts' and let it default to true. Then every sensible programmer would turn this setting off in new projects, and the problem is solved. Previous Comments: ------------------------------------------------------------------------ [2011-04-20 11:24:35] abe at siticompulsi dot net In my opinion converting a float to a string shouldn't consider locale settings. You can always use sprintf to do that. ------------------------------------------------------------------------ [2011-01-12 08:02:26] luke at cywh dot com While I understand the problem and do agree somewhat, this is something that shouldn't be ignored. At some point this should be fixed, even if it breaks backwards compatibility. Perhaps not in the 5.3.x, series, but at some point in the future it should. The problem, as I see it, is locale is not respected when converting a string to a float, as pointed out by the bug report you mentioned. An ideal solution would be to introduce an ini setting that toggles the behavior. The default value "0" would result in the current behavior whereas "1" would make casting a string to float respect locale. That way developers can toggle it with ini_set when they want the more (correct) intuitive behavior. Later on the default can be changed to "1" and developers can set it back to "0" for backwards compatibility. Then in the distant future the setting can be removed. That would be the "safe way" of doing it. To be honest I'm not sure it would break very much... It's not particularly useful to not have float casting respect locale. Most people that are aware of this problem work around it with their own floatval function that makes use of localeconv(). ------------------------------------------------------------------------ [2011-01-12 04:27:11] aharvey@php.net This may not be intuitive, or even particularly useful, but it is long standing (and intended) behaviour, per (among many others) bug #31963 and doc bug #38785. I don't see any way to change this without a massive backward compatibility break. ------------------------------------------------------------------------ [2011-01-10 23:48:02] luke at cywh dot com Description: ------------ When LC_ALL or LC_NUMERIC is used with setlocale casting a float as a string converts the number to the formatted locale (1234.56 to 1.234,56 instead of 1,234.56 for Italian). But when casting from a string to a float locale is not used and decimal precision is lost. I understand this has been a problem for a long time (since PHP 4 up to 5.3 at least). The obvious "work around" for me is avoid LC_NUMERIC and LC_ALL completely. Personally I would rather casting to a string NOT convert using the locale (so have it stay "1234.56"). A data type should not be locale aware. It's like assuming that a decimal number is monetary. If a float needed to be displayed with locale number_format should be used (where the default separators fit the locale). If casting to a string must be locale aware, shouldn't casting a string to a float be locale aware as well? On top of that, could it understand the thousands separator and simply ignore it? Test script: --------------- setlocale(LC_NUMERIC, 'en_US'); print (float)(string)1234.56; print '<br />'; setlocale(LC_NUMERIC, 'it_IT'); print (string)(float)(string)1234.56; print '<br />'; print (string)(float)'1.234,56'; Expected result: ---------------- 1234.56 1234,56 1234,56 Actual result: -------------- 1234.56 1234 1,234 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=53711&edit=1

« previous php.bugs (#184804) next »