Bug #53711 [Com]: Casting float->string->float with locale
| From: | marc at lithia dot nl | 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