Comparison between 2 equal numbers returning 'false'?

Asked

Viewed 1,092 times

3

I have the following code:

<?php var_dump($fullprice) ?>
<?php var_dump($cart->getData('subtotal')) ?>
<?php var_dump($fullprice == $cart->getData('subtotal')) ?>
  • $fullprice returns the sum of all products and quantities in the cart.
  • $cart->getData('subtotal') returns the subtotal in the cart.

The result:

float(319.2) 
float(319.2) 
bool(false)

Why this? The 2 values are equal, at least they were printed equal, but the dump returns false?

Edit: The whole code here

<?php /*----------  ##HACK##  ----------*/?>
<?php $cart = Mage::getModel('checkout/cart')->getQuote(); ?>
<?php $fullprice = 0; ?>
<?php foreach ($cart->getAllVisibleItems() as $item): ?>
    <?php $fullprice += ($item->getProduct()->getPrice() * $item->getQty()); ?>
<?php endforeach; ?>

<?php var_dump($fullprice) ?>
<br>
<?php var_dump($cart->getData('subtotal')) ?>
<br>
<?php var_dump($fullprice == $cart->getData('subtotal')) ?>

<?php if ($fullprice - $cart->getData('subtotal') > 0): ?>
    <p style="color: #319e49; font-size: 16px;">
        <?php echo "Você economizou R$", number_format($fullprice - $cart->getData('subtotal'), 2, ',', ''), "</br>" ?>
</p>
<?php endif; ?>
<?php /*----------  ##/HACK##  ----------*/?>
  • Can you create an example with this incorrect result? seems to have something else interfering with the code.

  • $fullprice is an array? by the description you gave in the question it seems that this variable 'does' two things.

  • I put the full code, take a look

  • If you did it echo $cart->getData('subtotal') .'<br>'; echo $cart->getData('subtotal'); the same value is displayed?

  • 1

    I smell places not displayed with different values. You see 319.2, but the computer should see anything like 319.2 billion billion times vs. 319.2 billion billion years ago. Round to two decimal places (or as many needed pro as you want) when comparing non-whole types.

  • @rray returned: 319.2&#xA;319.2&#xA;float(319.2) &#xA;float(319.2) &#xA;bool(false), the first 2 results referring to the code you recommended

  • 2

    Uses a number_format Set to display a 50 houses you will see why. : D

Show 2 more comments

2 answers

4


The problem is because the value of $fullprice or of $cart->getData('subtotal') is actually a real number extremely close to 319.2, something like 319.1999999999999. You can reproduce this case with the following test:

<?php

$x = 319.199999999999;
$y = 319.2;
var_dump($x);
var_dump($y);
var_dump($x == $y);

bash-4.2$ php test.php 
double(319.2)
double(319.2)
bool(false)

Floating point numbers are approximations with limited accuracy in computers because they use the binary system, which limits the representation accuracy of real numbers, so numbers with large numbers of decimals end up being rounded. In this case the value of $x is printed as 3.2 because the PHP display engine rounds numbers with a smaller number of decimals than the comparison engine, while a echo|var_dump will round up something like 319.1999999999999 the comparison (==) will only do the same to 319.1999999999999999 (has three more nines).

Note: A good introductory reference on the functioning of floating points is the php documentation on the subject.

2

This is about accuracy in PHP the same occurs in several other programming languages. what can be done to circumvent the problem is to use the absolute value of the difference of the two values and compare with the EPSILON constant that corresponds to 0.00001, if the difference is less than the count then the values can be considered equal

so let’s compare using as inspiration the code of our dear friend.

    <?php
    // abaixo valores hipotéticos obtidos no script
    // $fullprice tem o valor de: 319.2
    // $cart->getData('subtotal') retornará 319.2

    /* 
     aqui está a comparação que consegue determinar a 
igualdade a partir do valor absoluto da diferença dos
valores com ponto flutuante considerando que o 
resultado dessa diferença seja inferior 
a constante de EPSILON (0.00001)
    */
    if(abs($fullprice - $cart->getData('subtotal')) < 0.00001){
        echo "IGUAIS!";
    }
    else{
        echo "DIFERENTES!";
    }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.