views:

2192

answers:

4

Hi everyone, Got another math calculation problem again.

$a = 34.56

$b = 34.55

$a do some calculation to get this figure

$b is doing rounding nearest 0.05 to get this figure

what happen is

$c = $b - $a

supposedly I should be -0.01, but I echo out the $c is show -0.00988888888888

I try to use number_format($c, 2), but the output is 0.00,

how can I make sure $a and $b is exactly 2 decimals, no hidden number at the back.

in my php knowledge number_format only able to format the display, but the value not really 2 decimal,

I hope I can get help from here. This really frustrated me.

+1  A: 

Try sprintf ("%.2f", $c);

Floating point numbers are represented in IEEE notation based on the powers of 2, so terminating decimal numbers may not be a terminating binary number, that's why you get the trailing digits.

As suggested by Variable Length Coder, if you know the precision you want and it doesn't change (e.g. when you're dealing with money) it might be better to just use fixed point numbers i.e. express the numbers as cents rather than dollars

$a = 3456;

$b = 3455;

$c = $b - $a;

sprintf ("%.2f", $c/100.0);

This way, you won't have any rounding errors if you do a lot of calculations before printing.

Charles Ma
thanks for your answer, the only way is to format the output, it is not possible to just set it to 2 decimal, except using String.
Shiro
If you want to just set it to 2 decimals, you should be using fixed-point numbers, not floating-point. See Variable Length Coder's answer.
Carl Norum
I not really understand what does it means by "fixed-point" numbers, can you kindly provide some example? Thanks a lot!
Shiro
I guess by 'fixed point' he means to multiply any floating point numbers by the precision you want to make it into an integer. So for 2 decimal place numbers, instead of using a floating point to represent dollar amounts, use a integer to represent the amount in cents.
Charles Ma
+2  A: 

Use round():

$c = round($b - $a, 2);

Note: you can also choose the rounding mode as appropriate.

Edit: Ok I don't get what sprintf() is doing that number_format() isn't:

$c = number_format($b - $a, 2);

vs

$c = sprintf("%.2f", $b - $a);

?

cletus
Probably nothing, but sprintf() is a lot more fun to use for guys like me who are accustomed to C. Also saves one writing `$foo = number_format($b - $a, 2) . " apples!"` and instead writing `$foo = sprintf("%.2f apples!", $b - $a)` -- much more elegant, in my opinion.
Jed Smith
Round rocks, maybe cause that's all I know for now, still learning.
Newb
+1  A: 

You've run into one of the traps of floating point numbers; that they cannot always represent exact decimal fractions. If you want exact decimal values, you're better off using integers and then dividing by the precision you want at the end.

For example, if you're doing calculations in floats represeting Dollars (or your favorite currency), you may want to actually do your calculations in integer cents.

Variable Length Coder
can you please give an example how integer cents work? Not really get what you means. Thanks a lot for your comment.
Shiro
"Integer cents" means that, for example, the amount $24.95 should be stored not as a floating-point 24.95, but rather as the integer 2495. The amount $10.00 would be stored as the integer 1000. And so forth.
Robert L
A: 

You can very neatly sidestep all of these issues simply by using the bcmath library.

Just remember to read the documentation and be careful whether you are passing arguments as strings or as numeric datatypes.

Robert L