Withdraw several percentages proportional to a single value

0

Good afternoon everyone! I'm experiencing small problem here with percentage calculation and I'm having a hard time getting to the ultimate goal.

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

Let's try to calculate:

Firstly I have these recipients, 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 of the purchase, in this 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 that 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 recipient, taking its percentage relative to the purchase and added in the set of eachPercents , also converting from cents to decimal and rounding the percentage.

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

Where am I wrong. Thanks in advance. Hugs!

    
asked by anonymous 03.10.2016 / 20:12

1 answer

1

The problem is in the percentage formula.

($recipientAmount * $totalAmount) / 100

Should be

($recipientAmount * 100) / $totalAmount

That's enough to solve the problem. If you'd like to know more, read on.





Speaking a little more about the subject and presenting some suggestions and observations:

The formula that calculates percentage

A * 100 / T

A - > Value of which you want to get the percentage in relation 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 cents conversion is divided by 100. But the math expression will multiply by 100. So it's a redundant process, within your specific case. It could simplify without converting the cents.

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;
}

Note about round ()

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

You are eating 1%. Maintain fractional integrity. Unless the business model really wants to "eat" those small fractions. At this point I can not comment.

    
03.10.2016 / 20:52