Skip to content
Advertisement

Spread amount across multiple variables

Wondering if there is an elegant way to do this using a single function instead of writing something custom.

For example I want to separate 100$ into 3 parts (which do NOT have to be equal).

If I simply do 100/3 then each part will be 33.33$.

1 => 33.33
2 => 33.33
3 => 33.33

If I combine these parts back together it will return 99.9 instead of 100.

How can I make it separate the value into 3 parts with one of them being being different so when combined together it will equal 100$ and not 99.9$

1 => 33.34
2 => 33.33
3 => 33.33

I wrote this function, but hoping there’s a one liner that I can use instead

function adjust_parts($total, $parts) {

    // If total does not equal the sum of all the parts
    if(array_sum($parts) != $total) {

        // Keep adding a penny until it's "properly" spread
        $adjusted = false;
        while ($adjusted == false) {
            $parts[0] += 0.01;
            if(bccomp(array_sum($parts), $total, 2) == 0) {
                $adjusted = true;
            }
        }

    }

    return $parts;

}

Thank you

Advertisement

Answer

You could make up your $parts array of $pieces-1 copies of $total/$pieces, rounded to an appropriate precision, and then just push a final value which is $total minus the sum of the existing parts. For example:

$total = 100;
$pieces = 3;
$precision = 2;
$parts = array_fill(0, $pieces - 1, round($total / $pieces, $precision));
$parts[] = number_format($total - array_sum($parts), $precision);
print_r($parts);

Output

Array
(
    [0] => 33.33
    [1] => 33.33
    [2] => 33.34
)

Demo on 3v4l.org

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement