PHP Bugs  
php.net | support | documentation | report a bug | advanced search | search howto | statistics | login

go to bug id or search bugs for  

Bug #17079 setlocale changes the internal representation of floats
Submitted:7 May 2002 2:02pm UTC Modified: 24 Mar 2003 10:18am UTC
From:jonathan at tricolon dot com Assigned to:hholzgra
Status:Bogus Category:Scripting Engine problem
Version:4.3.0 RC2 OS:Red Hat Linux 7.1
Votes:6 Avg. Score:4.8 ± 0.4 Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%) Same OS:1 (50.0%)
View/Vote Developer Edit Submission

[7 May 2002 2:02pm UTC] jonathan at tricolon dot com
If I set my locale to Dutch in my php-script that converts currencies
for a Dutch site, I noticed that also the internal representation of
floats change as well. In Europe an amount of tenthousand dollars is
written as follows: $10.000,00 unlike the USA $10,000.00
So if I set the locale to "nl_NL" the internal representation of a float
with a point to seperate the integer part from the decimals (for
example: $amount = 68.123) is changed to a representation of a comma
','. I would like to see it changed because it messes up calculations
and the different locale settings should (IMHO) apply only to output
function and such.

Thanks,
Jonathan
[7 May 2002 2:36pm UTC] mfischer@php.net
This is dangerous indeed. We've had already reports about this (forgot
#, or did it even only came up on php-dev@?).

Though It may sound trivial, please provide a short self-contained
script showing the (mis-)behaviour.

Marking as critical for now.
[8 May 2002 4:14am UTC] jonathan at tricolon dot com
Hi somehow it has to do with converting 'numberic'-strings to floats as
the script below shows:

<?

$rate1 = 1.123;
$amount1 = 5;
$rate2 = "1.123";
$amount2 = "5";

// set locale to English to handle the floatingpoints correctly
// first calculation with floats
setlocale (LC_ALL, 'en_US');
echo "This should be correct:<br><br>";
echo $rate1." * ".$amount1." = ".($rate1*$amount1);

// second calculation with floats converted from strings
echo "<br><br>This should be correct as well:<br><br>";
echo $rate2." * ".$amount2." = ".($rate2*$amount2);

// set locale to Dutch to show misbehaviour
// first calculation with floats
setlocale (LC_ALL, 'nl_NL');
echo "<br><br>This should still be correct:<br><br>";
echo $rate1." * ".$amount1." = ".($rate1*$amount1);

// second calculation with floats converted from strings
echo "<br><br>This should be wrong:<br><br>";
echo $rate2." * ".$amount2." = ".($rate2*$amount2);

?>

Hope this shows the 'bug' correctly!
[23 May 2002 10:44am UTC] jonathan at tricolon dot com
I didn't hear anything anymore, so I am just curious if this was picked
up... Thanks, Jonathan
[28 Aug 2002 9:14pm UTC] sniper@php.net
one more locale bug..
[10 Oct 2002 11:53am UTC] iliaa@php.net
This bug has been fixed in CVS.

In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.

[3 Dec 2002 7:41am UTC] flying at dom dot natm dot ru
This bug seems to be still available. Àt least i can reproduce it with
4.3.0RC2 on Windows 2000 with locale set to 'ru'. 

<?php
setlocale (LC_ALL, 'en');
echo ('1.123'*'5').'<br>';
echo ('1,123'*'5').'<br>';
setlocale (LC_ALL, 'ru');
echo ('1.123'*'5').'<br>';
echo ('1,123'*'5').'<br>';
?>

Results are:
5.615
5
5
5,615
[16 Dec 2002 5:22am UTC] jonathan at tricolon dot com
As Alexander points out, the bug is still available.
[16 Dec 2002 8:46am UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

You should not use ',' to represent floats ALWAYS use '.' regardless of
locale.
[16 Dec 2002 8:56am UTC] jonathan at tricolon dot com
> You should not use ',' to represent floats
> ALWAYS use '.' regardless of locale.

This is exactly the problem. When the locale is changed to Dutch the
internal representation of floats is changed. The separator used is
changed to ','. This behaviour is incorrect and should be fixed. Check
my initial and second post for a detailed description.

Thanks,
Jonathan
[16 Dec 2002 7:45pm UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

If you switch to a locale where the float separator is ',' then when it
comes to output the data back to the user the float decimal point will
be depedant on the specified locale. Internally however it'll always be
'.'.
[2 Jan 2003 10:13am UTC] martin at mermaidconsulting dot com
I also ran across this problem and have been messing with it for like 3
days before i finally ran across this post. 

If you do not consider it a bug I would recommend you at least include
it in the documentation and make it very clear that you cannot perform
calculations using thousands-seperators based on the locale settings. 

If you have a look at the following sample you can see that user-inputs
will get totally messed up in case they use thousand-seperators.

<?
setlocale(LC_NUMERIC, "en_US") ; // setting the numeric locale to
us-conventions
setlocale(LC_MONETARY, "en_US") ; // setting the monetary locale to
us-conventions

$locale_info = localeconv();
  echo "mon_decimal_point: {$locale_info["mon_decimal_point"]}<br>"; //
displays the monetary decimal point used for the locale
  echo "mon_thousands_sep: {$locale_info["mon_thousands_sep"]}<br>"; //
displays the monetary thousands seperator used for the locale
  echo "decimal_point: {$locale_info["decimal_point"]}<br>"; // displays
the
decimal point used for the locale
  echo "thousands_sep: {$locale_info["thousands_sep"]}<br>"; // displays
the
thousands seperator used for the locale

// defines 2 variables that should be 1000000 and 750000
$a = "1,000,000";
$b = "750,000";

print "A = $a<br>";
print "B = $b<br>";

// performing a simple calculation that illustrates how PHP handles the
numbers
print "A * 1 = " . ($a*1) . "<br>";
print "B * 1 = " . ($b*1) . "<br>";
?>

Imho there is no point in having locale settings for currencies and
numeric values if you cannot use it for doing calculations.

Thanks

/Martin
[2 Jan 2003 1:58pm UTC] php at zeguigui dot com
I switched to PHP 4.3 (in dev only) and I saw this change in locale
handling. It is not OS dependant as I have the problem with Windows XP.

In PHP < 4.3.0 I have a MySQL database with floats. To handle those
floats I had to make some convertions (with str_replace) as results were
not locale dependant (I use fr_FR). For instance if I had 1.234 stored
in db, $row = mysql mysql_fetch_row($handle) would return in $row[0] the
value "1.234" and $row[0] * 100 would return 100 whereas of 123,4 (if
outputed).

In PHP = 4.3.0 I do not need those convertion routines anymore (it was a
workaround in my opinion).

So starting with PHP 4.3:
$a = 1.234 ==> OK whatever locale is
$b = "1.234" ==> OK whatever locale is
$c = "1,234" ==> NOT OK whatever locale is

If I have some user inputs I have to convert from locale representation
to number representation before processing them... it would be great to
have a function that do the job for us (didn't find one, sorry!)... but
maybe that's not the good place to ask for this!
[24 Mar 2003 10:18am UTC] moriyoshi@php.net
Related discussion:
http://news.php.net/article.php?group=php.dev&article=95211
[5 Jul 2003 6:13am UTC] dMNz at one dot lt
am pabandymuj..
[23 Oct 2004 4:58pm UTC] erki at lap dot ttu dot ee
Having the setlocale function in string.c execute 

if ((lc.decimal_point)[0] != '.') {
	/* set locale back to C */
	setlocale(LC_NUMERIC, "C");	
}

is not a solution. The particular "fix" broke other things. In many
countries, comma is used as a decimal separator. Case in point: 3 weeks
ago, a certain financial database of a major telco company in Europe was
upgraded to use PHP 4.3.8 (formerly 4.2.2). The system uses Oracle for
persistence, where the decimal separator is a comma, as is a custom in
that country. So numbers came in from Oracle, and then PHP was unable to
process them correctly. For example, if a client had a debt of 25,12€,
and the client paid 5€, then the comparison ($paid_amount > $debt) said
incorrectly that the paid amount was more than the debt.

Result: hundreds of wasted man-hours. In the end we recompiled PHP
without that "fix".

RSS feed | show source 

PHP Copyright © 2001-2009 The PHP Group
All rights reserved.
Last updated: Sat Nov 21 10:30:49 2009 UTC