skip to Main Content

After reading about comparing float numbers, I wrote the following comparison:

$profitMarginPercent = (($clientTotal - $vendorTotal)/$vendorTotal) * 100;

if(abs($clientTotal - $vendorTotal) > PHP_FLOAT_EPSILON) {
    $profitMarginPercent = "+".round($profitMarginPercent, 2);
}
elseif(abs($clientTotal - $vendorTotal) < PHP_FLOAT_EPSILON) {
    $profitMarginPercent = "-".round($profitMarginPercent, 2);
}
elseif(abs($clientTotal - $vendorTotal) == PHP_FLOAT_EPSILON) {
    $profitMarginPercent = round($profitMarginPercent, 2);
}

I want to print, for example, -50% if $vendorTotal is greater than $clientTotal or +50% if the other way round.

This works but with some exceptions:

  1. If $clientTotal is 0.00000 and $vendorTotal is any positive number, e.g. 14.72, my code prints +-100.

  2. If the two variables are equal, e.g. 89.64110, my code prints -0.

Can you explain why this is happening and how I can fix it?

2

Answers


  1. Here is a solution based on sprintf():

    function format($val)
    {
        if(abs($val) < 1e-6)
            return '0%';
        else
            return sprintf('%+.2f%%', $val);
    }
    
    echo format(1.234), PHP_EOL;
    echo format(1e-8), PHP_EOL;
    echo format(-1.234), PHP_EOL;
    

    Output:

    +1.23%
    0%
    -1.23%
    

    Small values are considered equal to zero.

    Login or Signup to reply.
  2. I would go with something like this:

    $profitMarginPercent = round((($clientTotal - $vendorTotal + PHP_FLOAT_EPSILON)/$vendorTotal) * 100, 2);
    $profitMarginPercent = ($profitMarginPercent > 0.0 ? "+" : "") . $profitMarginPercent;
    

    and then most likely put it in a function or method.

    See: https://3v4l.org/j5BR7

    What does it do?

    As you can see I add PHP_FLOAT_EPSILON to the numerator of the division, this is to prevent a negative result when the numerator and denominator have the same value. It’s a very small value, and you round to two decimals, so it never changes the outcome.

    Then it adds a + character in front of the number whenever $profitMarginPercent is positive. The - character is already there when the value is negative.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search