17

I have two variables, $_REQUEST['amount'] and $carttotal, on an e-commerce thing. They of course should match when attempting to process a payment, so as to prevent a manual override of the payment amount at the last minute, or of course, a calculation error.

However:

$carttotal = $carttotal * 1; $_REQUEST['amount'] = $_REQUEST['amount'] * 1; if($carttotal != $_REQUEST['amount']) { $code = 0; // cart empty under this user - cannot process payment!!! $message = 'The cart total of ' . $carttotal . ' does not match ' . $_REQUEST['amount'] . '. Cannot process payment.'; $amount = $carttotal; $json = array('code' => $code, 'message' => $message, 'amount' => $amount); die(json_encode($json)); } else { $trnOrderNumber = $client->id . '-' . $carttotal; } 

The above code, with the same numbers passed, is NOT giving me the equal. Basically I get the error message as if the $carttotal != $_REQUEST['amount'] is true (unequal vars).

So to test the vars, I snuck in:

var_dump($_REQUEST['amount']); var_dump($carttotal); 

To see what is going on (after I do the * 1 calculations to make sure they are dealt with as floats, not strings).

I got this back:

float(168.57) float(168.57) 

Very very frustrating. What could be causing this?

6
  • in PHP, if you are using the != instead of !== the variable type should not matter as it will normalize the variable types when doing the comparison. Commented Dec 3, 2011 at 0:03
  • dqhendricks - ya that's what I figured. With a != rather than !== I thought it wouldn't be too strict. The number of decimals match etc. $carttotal is calculated by iterating through rows of products & taxes & quantity, so I expected the float to have some oddities with the decimal points. however it is forced to 2 decimals, as is the amount, so I figured it may work with a simple != comparison but I guess not. Commented Dec 3, 2011 at 0:08
  • 1
    Sorry @jeffkee, that was a bit condescending, I'm sorry. It's just "why don't my floating point numbers equate" is probably the most commonly asked duplicate question here. Commented Dec 4, 2011 at 12:32
  • 1
    It's a commonly asked question because it defies common logic, and the perception that computer calculations are precise to every digit possible - that is the "human" perception of numbers & computer logics. Now we have another page that will be crawled on Google with more related keywords, so that there's a higher chance somebody else will find it without having to post. P.S. I did know a bit about this - however I thought that when I do a vardump() it would still show the infinite number of decimals such as 168.5699999991233521 so that was the really confusing part. Commented Dec 7, 2011 at 19:50
  • 1
    It's actually a problem with var_dump and printing floats. Commented Nov 17, 2015 at 21:40

3 Answers 3

16

floating point numbers have limited precision. view the warning about comparing them here:

http://php.net/manual/en/language.types.float.php

Sign up to request clarification or add additional context in comments.

1 Comment

For anyone looking, try bcmath. You may need to install bcmath extension in your apache.
6

Floating point numbers are NOT 100% accurate! You calculation in PHP may return 10.00000000001 which is NOT equal to 10.

Use sprintf ( http://php.net/manual/en/function.sprintf.php ) to format the floats before you compare them.

Comments

0

Instead of multiplying by one use number_format.

 $carttotal = number_format((int)$carttotal,2,'.',''); $_REQUEST['amount'] = number_format((int)$_REQUEST['amount'],2,'.',''); 

2 Comments

The number_format will make a string from the number, from my opinion it's not recommended this operation
Also, you are casting the amount to an integer, so any numbers after the decimal are now disregarded. 11.20 would equal 11.99

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.