danbopes Posted August 29, 2008 Share Posted August 29, 2008 Take a look at this, I am completely and utterly stumped. I have about 5 years of experience, and I really believe I have come across a bug. Inside of an object: fwrite($logFd, $this->my_var_dump((floatVal('49.95') == floatVal('49.95')))); $my_total = ($_POST['mc_gross'] + ($this->account_total($user_id))); $test = $this->my_var_dump($my_total == $total); $test2 = $this->my_var_dump($my_total); $test3 = $this->my_var_dump($total); fwrite($logFd, $test . ',' . $test2 . ',' . $test3); $this->my_var_dump($var) simply just dumps the var, to a variable instead of to the browser. Refer to var_dump on the php website. This is what I get in the file: bool(true) bool(false) ,float(49.95) ,float(49.95) I am seriously like WTF. $this->account_total simply pulls from a database: function account_total($user_id) { // BE SURE TO GET A FRESH ROW! $this->user->user_info is session based, and may not be up to date! $row = $this->db->getRow("SELECT `account_type`, `static_balance`, `dynamic_balance` FROM `users` WHERE `id` = " . $user_id); if ( empty($row) ) return '0.00'; if ( $row['account_type'] > 1 ) return number_format($row['static_balance'] + $row['dynamic_balance'], 2); else return '0.00'; } I just want to add them up and do a bit of checking, but idk whats wrong. Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 Where are you setting $total? >_> Quote Link to comment Share on other sites More sharing options...
danbopes Posted August 29, 2008 Author Share Posted August 29, 2008 Look at $test3 Quote Link to comment Share on other sites More sharing options...
discomatt Posted August 29, 2008 Share Posted August 29, 2008 Could you provide us with a self-contained script to re-create this scenario. There is a lot going on that we can't see that could be affecting your results. Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 Look at $test3 Yeah, I saw it, danbopes, but I still want to know where it's coming from. @discomatt: I was just about to make something to try to recreate it, lol. But it would be better if he did. Quote Link to comment Share on other sites More sharing options...
akitchin Posted August 29, 2008 Share Posted August 29, 2008 have you tried dumping $my_total and $total BEFORE trying the conditional? Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 I mean, if I do: <?php $_ = 49.95; $__ = 49.95; var_dump($_ == $__); ?> I get: bool(true) So can you give us a better code example of what's actually going on so we can try it? >_> Quote Link to comment Share on other sites More sharing options...
danbopes Posted August 29, 2008 Author Share Posted August 29, 2008 <?php $_POST['mc_gross'] = '0.80'; class paypal_IPN { function process() { $total = 49.95; $my_total = ($_POST['mc_gross'] + ($this->account_total($user_id))); var_dump($my_total == $total); var_dump($my_total); var_dump($total); } function account_total($user_id) { return 49.15; } } //end of class $index = new PayPal_IPN(); $index->process(); ?> Quote Link to comment Share on other sites More sharing options...
discomatt Posted August 29, 2008 Share Posted August 29, 2008 <?php $a = '14.95'; $b = 14.95; var_dump( $a == $b ); # bool(true) var_dump( $a === $b ); # bool(false) var_dump( (float)$a === $b ); # bool(true) ?> Quote Link to comment Share on other sites More sharing options...
danbopes Posted August 29, 2008 Author Share Posted August 29, 2008 <?php $a = '14.95'; $b = 14.95; var_dump( $a == $b ); # bool(true) var_dump( $a === $b ); # bool(false) var_dump( (float)$a === $b ); # bool(true) ?> Do you even look at my code before you post? They are both floats...and I am checking to see if they are equal...why are you bringing in '===' to this? Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 Okay, now THAT is weird. Type-casting to floats doesn't work either, apparently. O_O Quote Link to comment Share on other sites More sharing options...
danbopes Posted August 29, 2008 Author Share Posted August 29, 2008 So just exactly what do I do? Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 Wow. Just figured something out, and I think you're right about there being a bug. I think PHP doesn't want to handle float equality correctly (not sure why), because if you typecast to a string, you get the correct result: <?php $_POST['mc_gross'] = '0.80'; class paypal_IPN { function process() { $total = 49.95; $my_total = ($_POST['mc_gross'] + ($this->account_total($user_id))); var_dump($my_total); var_dump($total); if ((string) $total == (string) $my_total) { echo "Same\n"; } else { echo "Not the same\n"; } } function account_total($user_id) { return 49.15; } } //end of class $index = new PayPal_IPN(); $index->process(); ?> Quote Link to comment Share on other sites More sharing options...
discomatt Posted August 29, 2008 Share Posted August 29, 2008 Nope, this makes sense... read up on float precision... To sum it up, binary data can't store a decimal number 'properly' so as soon as you add a number to it, you're gonna have inaccuracies that may not be present in 2-decimal accuracy Use this to correct it. var_dump((string)$my_total == (string)$total); Do you even look at my code before you post? They are both floats...and I am checking to see if they are equal...why are you bringing in '===' to this? I posted before I noticed you had replied. Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 Yeah, I was thinking of that too right after I realized that it worked with string typecasts. Well, problem solved I guess. @_@ Quote Link to comment Share on other sites More sharing options...
danbopes Posted August 29, 2008 Author Share Posted August 29, 2008 It's not solved, because I need to check to see if it's greater then or equal to, not equal to. We are dealing with small numbers here, I don't see why it would be messing up this badly. 0.80 + 49.15 is 49.95, I don't see how that can be any other thing. Both var_dumps are telling me it's both a float at 49.95, there is no reason this shouldn't be working. Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 var_dump((string) $my_total >= (string) $total); >_> Quote Link to comment Share on other sites More sharing options...
jordanwb Posted August 29, 2008 Share Posted August 29, 2008 It's not solved, because I need to check to see if it's greater then or equal to, not equal to. Convert to string. Get all the numbers before and after the decimals and type-cast to int and compare. Quote Link to comment Share on other sites More sharing options...
discomatt Posted August 29, 2008 Share Posted August 29, 2008 It's not solved, because I need to check to see if it's greater then or equal to, not equal to. We are dealing with small numbers here, I don't see why it would be messing up this badly. 0.80 + 49.15 is 49.95, I don't see how that can be any other thing. Both var_dumps are telling me it's both a float at 49.95, there is no reason this shouldn't be working. Learn how computers store float values as binary data, and you will find the reason. Why do you think most database engines have both FLOAT and DECIMAL type columns? Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 It's not solved, because I need to check to see if it's greater then or equal to, not equal to. We are dealing with small numbers here, I don't see why it would be messing up this badly. 0.80 + 49.15 is 49.95, I don't see how that can be any other thing. Both var_dumps are telling me it's both a float at 49.95, there is no reason this shouldn't be working. Learn how computers store float values as binary data, and you will find the reason. Why do you think most database engines have both FLOAT and DECIMAL type columns? Oh oh, I know! Pick me, pick me! Pleeeeeeease! Anyway, yeah, don't gripe about it if you don't understand what's actually going on. Quote Link to comment Share on other sites More sharing options...
jordanwb Posted August 29, 2008 Share Posted August 29, 2008 Why do you think most database engines have both FLOAT and DECIMAL type columns? For reduncancy? If one type fails the other will pick up the slack? Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 Why do you think most database engines have both FLOAT and DECIMAL type columns? For reduncancy? If one type fails the other will pick up the slack? DECIMAL handles precision better than FLOAT. Quote Link to comment Share on other sites More sharing options...
jordanwb Posted August 29, 2008 Share Posted August 29, 2008 DECIMAL handles precision better than FLOAT. I see. How come with computers 'they' have a hard time handling floating point numbers but calculators seem to have no problem? Quote Link to comment Share on other sites More sharing options...
DarkWater Posted August 29, 2008 Share Posted August 29, 2008 DECIMAL handles precision better than FLOAT. I see. How come with computers 'they' have a hard time handling floating point numbers but calculators seem to have no problem? They do. You just don't see it. Quote Link to comment Share on other sites More sharing options...
jordanwb Posted August 29, 2008 Share Posted August 29, 2008 All right. Good enough for me. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.