(0.7/0.001)%10 is not returning 0

103 views Asked by At

I am creating a bitcoin based ad platform for a bitcoin learning portal. The reason I mention it is, I believe, it'll help to understand my problem and thereby I may get a better solution. What am I doing is simply passing the amount an user will pay from an HTML form to a PHP page and checking whether it is a multiple of 10. The code snippet is as follows...

$orderAmount = $_POST['orderAmount'];
$adUnitPrice = 0.001;
if((($orderAmount/$adUnitPrice) % 10) == 0)
    $standardPayment = true;
else
    $standardPayment = false;

When I am passing $orderAmount as 0.6 or 0.8, I get the expected return of $standardPayment = true. But, when I am passing $orderAmount as 0.7, I get the unexpected return of $standardPayment = false !!! Can someone please tell me what is the problem and how to fix this ?

2

There are 2 answers

0
rkmax On BEST ANSWER

bcmath module can help you

bcmod(bcdiv("0.7", "0.001"), "10"); // returns 0

in your code

$orderAmount = $_POST['orderAmount'];
$adUnitPrice = 0.001;
if(bcmod(bcdiv($orderAmount, $adUnitPrice), 10) == 0) {
    $standardPayment = true;
} else {
    $standardPayment = false;
}

or even

$standardPayment = (bcmod(bcdiv($orderAmount, $adUnitPrice), 10) == 0);

you can check on command line with php -m and look if has the module or write a file with the follow

<?php phpinfo(); ?>

and look if has enable the module bcmath

3
Alnitak On

Neither 0.7 or 0.001 are exactly representable in IEEE 754 floating point math - see numerous other related questions here.

Hence when you divide 0.7 by 0.001 you do not get exactly 700, but something very close to 700 instead (probably 699.99999999999988631316) and therefore the modulus test fails.

You should round your price to the nearest cent (or 10th of a cent, or similar) and then perform your "standard payment" test.