My PHP math is calculating weird!

Reply

Join Date: May 2005
Posts: 232
Reputation: nathanpacker is an unknown quantity at this point 
Solved Threads: 0
nathanpacker's Avatar
nathanpacker nathanpacker is offline Offline
Posting Whiz in Training

My PHP math is calculating weird!

 
0
  #1
Mar 3rd, 2008
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:

  1. $query = mysql_query("SELECT * FROM mytable WHERE id=1") or die(mysql_error());
  2. while($row = mysql_fetch_array($query))
  3. {
  4. $net=$row['net']/100;
  5. }

So at this point, $net=2000. Here's how I get the $sum variable:

  1. $query = "SELECT SUM(allotment) FROM anothertable";
  2. $result = mysql_query($query) or die(mysql_error());
  3. while($row = mysql_fetch_array($result))
  4. {
  5. $sum=$row['SUM(allotment)']/100;
  6. }

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:

  1. $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:

  1. $sum=$row['SUM(allotment)'];

And

  1. $net=$row['net'];

Then calculate the leftover amount from those like this:

  1. $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.
Reply With Quote Quick reply to this message  
Join Date: Jul 2006
Posts: 155
Reputation: mostafadotnet is on a distinguished road 
Solved Threads: 10
mostafadotnet's Avatar
mostafadotnet mostafadotnet is offline Offline
Junior Poster

Re: My PHP math is calculating weird!

 
0
  #2
Mar 3rd, 2008
solve it like this:
  1. echo round($leftover, 2);

Good luck.
Reply With Quote Quick reply to this message  
Join Date: Apr 2006
Posts: 66
Reputation: silviuks is an unknown quantity at this point 
Solved Threads: 11
silviuks silviuks is offline Offline
Junior Poster in Training

Re: My PHP math is calculating weird!

 
0
  #3
Mar 3rd, 2008
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.
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 165
Reputation: Fest3er is an unknown quantity at this point 
Solved Threads: 18
Fest3er Fest3er is offline Offline
Junior Poster

Re: My PHP math is calculating weird!

 
0
  #4
Mar 5th, 2008
Originally Posted by nathanpacker View Post
... So 2000-1999.94 should equal 0.06 right? I just don't understand!
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.
Reply With Quote Quick reply to this message  
Join Date: May 2005
Posts: 232
Reputation: nathanpacker is an unknown quantity at this point 
Solved Threads: 0
nathanpacker's Avatar
nathanpacker nathanpacker is offline Offline
Posting Whiz in Training

Re: My PHP math is calculating weird!

 
0
  #5
Mar 6th, 2008
Originally Posted by Fest3er View Post
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.
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. Shouldn't be that dificult, rught? Well, I think I'm happy with the way I'm doing it now, like I mentioned at the last part of my post, where I do the division by 100 at the very end. I was just curious.

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.
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 165
Reputation: Fest3er is an unknown quantity at this point 
Solved Threads: 18
Fest3er Fest3er is offline Offline
Junior Poster

Re: My PHP math is calculating weird!

 
0
  #6
Mar 6th, 2008
Originally Posted by nathanpacker View Post
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. ...
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.
Reply With Quote Quick reply to this message  
Join Date: May 2005
Posts: 232
Reputation: nathanpacker is an unknown quantity at this point 
Solved Threads: 0
nathanpacker's Avatar
nathanpacker nathanpacker is offline Offline
Posting Whiz in Training

Re: My PHP math is calculating weird!

 
0
  #7
Mar 6th, 2008
Originally Posted by Fest3er View Post
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.
Ah, gotcha. Well then, how do calculators do it so well dang it? (you don't have to answer that. Semi-rhetorical question.)
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC