php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #53711 Casting float->string->float with locale
Submitted: 2011-01-10 23:48 UTC Modified: 2011-01-12 08:02 UTC
Votes:22
Avg. Score:4.4 ± 1.0
Reproduced:20 of 21 (95.2%)
Same Version:10 (50.0%)
Same OS:6 (30.0%)
From: luke at cywh dot com Assigned:
Status: Wont fix Package: Math related
PHP Version: 5.2.17 OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please — but make sure to vote on the bug!
Your email address:
MUST BE VALID
Solve the problem:
34 + 2 = ?
Subscribe to this entry?

 
 [2011-01-10 23:48 UTC] 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

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-01-12 04:27 UTC] aharvey@php.net
-Status: Open +Status: Wont fix
 [2011-01-12 04:27 UTC] 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-12 08:02 UTC] 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-04-20 11:24 UTC] 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.
 [2014-03-16 20:49 UTC] marc at lithia dot nl
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.
 [2014-12-12 11:20 UTC] ajf at ajf dot me
marc, adding an ini setting would simply make library authors' lives more difficult, as now you have two possible behaviours to account for.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 04:01:28 2024 UTC