formatCurrency broken?

I am trying to localise currency display in a number of places including in a view that is part of a list.

Using formatCurrency I get a number of different results depending on what I do, none of them optimal. It seems that the format routine is treating the number as a float. The number is decimal(12,2) in the db.

The amounts are displayed fine when I just display the data. The problem is that the client wants the formatting according to the local European rules with thousands seperators, so I am trying formatCurrency.

Problem is that when I use




$cn=new CNumberFormatter('en');

echo $cn->formatCurrency($data->dst_amount, $data->src_curr->code);




I get a number like

€529.9099999999999682

instead of 529.91.

I have tried various different ways to pass the number in - using (string) or number_format but the end result seems always the same.


echo $cn->formatCurrency('529.92', $data->src_curr->code);

gives €529.9199999999999591

Is this a bug in formatCurrency?

This is due to your locale currency settings. Go and check your YII framework folder/i18n/data you will fix the problem there… Find your locale and fix it

I dont think so - I have tried a number of different locales with the same result. With “en” I see ‘currencyFormat’ => ‘¤#,##0.00;(¤#,##0.00)’ - that looks ok to me. Its something to do with the number being treated as a long rather than a string somewhere.

I have a fix for this but it involves an edit in the framework - am I off track?

In ii18n/Cnumberformatter.php

change line 162




$value=round($value,$format['maxDecimalDigits']);



to


$value=number_format($value,$format['maxDecimalDigits'],'.','');



That solves this problem. What I dont know is if it introduces others!

Well,

I have done this:




$cn=new CNumberFormatter('en_us');

echo $cn->formatCurrency('529.92', 'USD');



And the result is as expected $529,92… I am using latest version 1.18, which version are you using?

1.17 r3135

I will download 1.18 and see what happens. Thanks!

Problem still there with the latest version of yii. It is clear that your setup is giving a different result from round() to mine - hence the issue. I will research this in the php forums, but it will no doubt affect someone else sometime I would think.

round() should work too… if the second parameter is 2 it should return a number with 2 decimals… can you check the value of $format[‘maxDecimalDigits’] in your case where you are getting numbers like 529.9199999999999591…

Could you do some testing?

Could you log on your parseFormat function in CNumberFormatter, the Pattern that is passed to the function and the result? ie: echo $pattern on line 206, and echo CVarDumper::dumpAsString($format) on line 278

Lets see the results of that parsed pattern

I did all that and thats how I narrowed it down to the line with round(). I have found that without even using the yii functions


TEST : <?=round(529.92,2)?>

will produce TEST : 529.9199999999999591. On the other hand number_format() works fine (for me). No idea why, but this is the nub of the issue. Still trawling google on it …

maxDecimalDigits is correct at 2. If you see my fix above you will see the issue is in how my system treats round() - no idea why!

Here are some useful information - http://stackoverflow.com/questions/2187197/php-rounding-problem-5-2-3

Theres quite a bit floating around about the issues with floats, but none of this explains why I see the problem and others dont! Very simply - why does round() give me this error and number_format() not? Anyway - by changing the float() to number_format in CNumberFormatter I get around this issue - is there any reason why this cant be done in the framework?

As the php doc say… the float representation depends on the system…

The main difference is that round returns a float… and number_format returns a string…

I oppened an issue for this - http://code.google.com/p/yii/issues/detail?id=2591#c0

Let’s see what other developers say about this…