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
)