| | |
My PHP math is calculating weird!
Please support our PHP advertiser: PostgreSQL or MySQL? Compare and contrast the two most popular open source databases
![]() |
Hey, I've got some values that don't seem to be calculating correctly. I've got two numbers, subtracting one from another, and instead of the answer being an exact number, like .06, it's coming out as like .0599999999.
For some background, I'm working with monetary values, and since I'm so new to php and don't know of a better way, I'm simply converting all numbers to cents in the database by multiplying everything by 100, and if I'm spitting it out to the screen for the user, I'm multiplying it by 100. So anyway, I'm taking one number, say $2000 (which is stored in the database as 200000), and assigning it to a variable say called $net.
The other number is being obtained from the sum of numbers in a table, and I'm calling it $sum.
So here's how I'm getting the $net variable. The value in the table that it is pulling is 200000:
So at this point, $net=2000. Here's how I get the $sum variable:
In this case, $sum=1999.94
So now I want to create a value called $leftover that is equal to $net minus $sum.
So I do this:
It should end up being .06, but it's not, it's ending up as .059999999. Any clues as to why?
Now I noticed that if in my while statement I set the variables like this:
And
Then calculate the leftover amount from those like this:
Then it works! Why?
FYI - I even printed out my variables as I went along to check them. Sure enough, it prints out:
$net=2000
$sum=1999.94
So 2000-1999.94 should equal 0.06 right? I just don't understand!
For some background, I'm working with monetary values, and since I'm so new to php and don't know of a better way, I'm simply converting all numbers to cents in the database by multiplying everything by 100, and if I'm spitting it out to the screen for the user, I'm multiplying it by 100. So anyway, I'm taking one number, say $2000 (which is stored in the database as 200000), and assigning it to a variable say called $net.
The other number is being obtained from the sum of numbers in a table, and I'm calling it $sum.
So here's how I'm getting the $net variable. The value in the table that it is pulling is 200000:
PHP Syntax (Toggle Plain Text)
$query = mysql_query("SELECT * FROM mytable WHERE id=1") or die(mysql_error()); while($row = mysql_fetch_array($query)) { $net=$row['net']/100; }
So at this point, $net=2000. Here's how I get the $sum variable:
php Syntax (Toggle Plain Text)
$query = "SELECT SUM(allotment) FROM anothertable"; $result = mysql_query($query) or die(mysql_error()); while($row = mysql_fetch_array($result)) { $sum=$row['SUM(allotment)']/100; }
In this case, $sum=1999.94
So now I want to create a value called $leftover that is equal to $net minus $sum.
So I do this:
php Syntax (Toggle Plain Text)
$leftover=$net-$sum;
It should end up being .06, but it's not, it's ending up as .059999999. Any clues as to why?
Now I noticed that if in my while statement I set the variables like this:
php Syntax (Toggle Plain Text)
$sum=$row['SUM(allotment)'];
And
php Syntax (Toggle Plain Text)
$net=$row['net'];
Then calculate the leftover amount from those like this:
php Syntax (Toggle Plain Text)
$leftover=($net-sum)/100;
Then it works! Why?
FYI - I even printed out my variables as I went along to check them. Sure enough, it prints out:
$net=2000
$sum=1999.94
So 2000-1999.94 should equal 0.06 right? I just don't understand!
Last edited by nathanpacker; Mar 3rd, 2008 at 12:41 am.
•
•
Join Date: Apr 2006
Posts: 66
Reputation:
Solved Threads: 11
you can also try to use number_format(float $value, int $decimals). the problem with this function is that returns a string so it will help you only for friendly display.
•
•
Join Date: Aug 2007
Posts: 165
Reputation:
Solved Threads: 18
•
•
•
•
... So 2000-1999.94 should equal 0.06 right? I just don't understand!
In a nut shell, you don't get exact answer all the time because binary floating point machine arithmetic cannot reproduce all real decimal numbers. Binary gets close, but cannot always be dead-nuts-on. It's been too long, but I'll bet that .06 cannot be exactly represented by a binary floating point number.See Wikipedia's IEEE Floating Point Standard page for more info.
•
•
•
•
To find the best answer, you have to travel 30 years back in time.In a nut shell, you don't get exact answer all the time because binary floating point machine arithmetic cannot reproduce all real decimal numbers. Binary gets close, but cannot always be dead-nuts-on. It's been too long, but I'll bet that .06 cannot be exactly represented by a binary floating point number.
See Wikipedia's IEEE Floating Point Standard page for more info.
On a side note, anyone have a better way of working with monitary values other than storing them in the database all as pennies? I mean, I kind of like it, it's simple, and easy to understand, just wondering if there's a better way.
•
•
Join Date: Aug 2007
Posts: 165
Reputation:
Solved Threads: 18
•
•
•
•
That's an interesting answer. I guess I'm just confused. If you divide something by 100, you end up with two decimal places, period. ...
101010110/1100100
What you see as 2-1.94, the computer computes as, generally speaking,
10-1.1111 = .0000111
If you convert 1.1111 (binary) back to decimal, you will get 1.9375.
A silly extension of this (1.94 conversion) to many decimal/binimal places:
1.1111000010100011110101110000101000111101011100001 (binary) =
1.9399999999999995026200849679298698902130126953125 (decimal), and
1.11110000101000111101011100001010001111010111000011 (binary) =
1.94000000000000039079850466805510222911834716796875
You can see that one bit at 49 binimal places still has a not insignificant effect on the value of the number.
And for .06:
0.100110011001100110011 (binary) =
.599999904632568359375 (decimal), and
0.1001100110011001100111 (binary) =
.6000001430511474609375 (decimal)
Only rarely can real decimal numbers be exactly represented by real binary numbers. 'Real numbers' here means floating point numbers, as opposed to whole (integer) numbers. Why? In decimal, the number to the right of the '.' are 1/10, 1/100, 1/1000, etc. In binary, those numbers are 1/2, 1/4, 1/8, 1/16, etc. They only rarely align.
People have tried to get rich adding up these lost millicents and microcents. Well, at least they've tried in the movies.
•
•
•
•
But, grasshopper, you are forgetting that the computer does not operate in the decimal realm. It operates in the binary realm. What you think is 342/100, the computer sees as:
101010110/1100100
What you see as 2-1.94, the computer computes as, generally speaking,
10-1.1111 = .0000111
If you convert 1.1111 (binary) back to decimal, you will get 1.9375.
A silly extension of this (1.94 conversion) to many decimal/binimal places:
1.1111000010100011110101110000101000111101011100001 (binary) =
1.9399999999999995026200849679298698902130126953125 (decimal), and
1.11110000101000111101011100001010001111010111000011 (binary) =
1.94000000000000039079850466805510222911834716796875
You can see that one bit at 49 binimal places still has a not insignificant effect on the value of the number.
And for .06:
0.100110011001100110011 (binary) =
.599999904632568359375 (decimal), and
0.1001100110011001100111 (binary) =
.6000001430511474609375 (decimal)
Only rarely can real decimal numbers be exactly represented by real binary numbers. 'Real numbers' here means floating point numbers, as opposed to whole (integer) numbers. Why? In decimal, the number to the right of the '.' are 1/10, 1/100, 1/1000, etc. In binary, those numbers are 1/2, 1/4, 1/8, 1/16, etc. They only rarely align.
People have tried to get rich adding up these lost millicents and microcents. Well, at least they've tried in the movies.
![]() |
Other Threads in the PHP Forum
- Previous Thread: Looking for experienced PHP programmer for online sim game.
- Next Thread: Form Crapped Out...
| Thread Tools | Search this Thread |
apache api array beginner binary body broken buttons cakephp checkbox class cms code cron curl database date date/time display dynamic ebooks echo email error file files folder form forms function functions global google href htaccess html image include insert ip javascript joomla limit link list login mail mediawiki menu mlm msqli_multi_query multiple mycodeisbad mysql number oop parameter paypal pdf php phpincludeissue phpmyadmin problem query radio random recursion regex remote script search seo server sessions sms source sp space speed sql static subdomain syntax system table tag tutorial update upload url validator variable vbulletin video web webdesign white wordpress xml youtube





