Remove several percentages proportional to a single value

Asked

Viewed 163 times

0

Good afternoon guys! I’m facing little problem here with percentage calculation and I’m having trouble getting to the final goal.

I have to calculate the percentage difference of each recipient in the purchase, according to the total purchase. Where at the end the total sum of the percentage of each receiver has to hit 100%.

Let’s try to calculate:

First I have these receivers, each one already has its amount (they are in cents):

$recipients = [
      [
        "recipient_id" => "re_cisc9ja1e01u1gd6elgn8iudx",
        "charge_processing_fee" => false,
        "liable" => false,
        "amount" => 3000.0
      ],
      [
        "recipient_id" => "re_cisc9jb9c01we2m6dueafa586",
        "charge_processing_fee" => true,
        "liable" => false,
        "amount" => 1000.0,
      ],
      [
        "recipient_id" => "re_cisc9jbvz01wf2m6dogbkj6z1",
        "charge_processing_fee" => false,
        "liable" => true,
        "amount" => 7870.0,
      ]
];

What I need is to take the percentage of each of them compared to the total purchase, in which case the total would be 118.70. So I did this:

$eachPercents = [];
$totalAmount = totalAmount($recipients);

foreach ($recipients as $recipient) {
    $recipientAmount = cent_to_decimal($recipient['amount']);
    $recipientPercent = round(($recipientAmount * $totalAmount) / 100);

    array_push($eachPercents, $recipientPercent);
}

But the result this generates is inconsistent:

array:3 [▼
  0 => 36.0
  1 => 12.0
  2 => 93.0
]

36 + 12 + 93 = 141

The function totalAmount() returns me the total of the purchase according to what each recipient has, converted from cents to decimal. And the foreach passes each receiver, taking out its percentage relative to the purchase and added in the set of eachPercents, also converting from cents to decimal and rounding the percentage.

But as you can see, the percentages being returned are incorrect.

Where I am wrong. I thank you already. Hugs!

1 answer

1


The problem is in the percentage formula.

($recipientAmount * $totalAmount) / 100

Should be

($recipientAmount * 100) / $totalAmount

This is enough to solve the problem. If you want to know more, continue reading.





Talking a little more on the subject and making some suggestions and observations:

The formula that calculates percentage

A * 100 / T

A -> Value from which you want to obtain the percentage relative to T.

Example:

30 * 100 / 118.7 results in 25.273799494524

A generic example in PHP:

/*
O array original da pergunta não possui essa estrutura, mas fiz assim apenas para simplificar. é algo irrelevante.
*/
$arr = array(
    3000,
    1000,
    7870
);

// Transforma em centavos
$arr = array_map(function($v){return $v / 100;}, $arr);

$total = array_sum($arr);

echo 'total: '.$total.'<br>';

foreach ($arr as $v) {
    echo $v * 100 / $total.'<br>'.PHP_EOL;
}

Optimized alternative

Note that the conversion of cents is divided by 100. But the mathematical expression will multiply by 100. Therefore, it is a redundant process within your specific case. It could simplify without converting the pennies.

A new optimized version:

$arr = array(
    3000,
    1000,
    7870
);

//Pula essa bagaceira
//$arr = array_map(function($v){return $v / 100;}, $arr);

//Converte apenas o total
$total = array_sum($arr) / 100;

echo 'total: '.$total.'<br>';

foreach ($arr as $v) {
    // Aqui não foi necessário a multiplicação pois seria redundante
    echo $v / $total.'<br>'.PHP_EOL;
}

Comment on the round()

In the question code is applying rounding with the function round(). Evaluate well if you really want to apply the rounding, because the result will be 25, 8 and 66, whose sum makes 99%.

It’s eating 1%. Maintain fractional integrity. Unless the business model really wants to "eat" these small fractions. At this point I can’t give an opinion.

Browser other questions tagged

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