PHP-реализация алгоритма largest remainder method . Этот метод является наиболее распространенным способом избавиться от проблем округления при работе с округленными процентными значениями.
Предположим следующий пример:
18.562874251497007%
20.958083832335326%
18.562874251497007%
19.161676646706585%
22.75449101796407%
Округлив приведенные выше проценты с помощью функций округления PHP, мы получим:
19%
21%
19%
19%
23%
Что на самом деле в сумме составляет 101% вместо 100% . largest remainder method решает эту проблему, выполняя следующие шаги:
composer require " kschu91/largest-remainder-method "Если вы не знакомы с композитором: базовое использование композитора
$ numbers = [
18.562874251497007 ,
20.958083832335326 ,
18.562874251497007 ,
19.161676646706585 ,
22.75449101796407
];
$ lr = new LargestRemainder ( $ numbers );
print_r ( $ lr -> round ());что приводит к:
Array
(
[0] => 19
[1] => 21
[2] => 18
[3] => 19
[4] => 23
)
Точность по умолчанию установлена на 0 . Но вы можете изменить это поведение, используя метод setPrecision :
$ numbers = [
18.562874251497007 ,
20.958083832335326 ,
18.562874251497007 ,
19.161676646706585 ,
22.75449101796407
];
$ lr = new LargestRemainder ( $ numbers );
$ lr -> setPrecision ( 2 );
print_r ( $ lr -> round ());что приводит к:
Array
(
[0] => 18.56
[1] => 20.96
[2] => 18.56
[3] => 19.16
[4] => 22.76
)
В большинстве случаев у вас нет чисел, к которым вы хотите применить этот алгоритм, в простом массиве, как в примерах выше. Вы предпочитаете хранить их в объектах или ассоциативных массивах. Вот почему эта библиотека также поддерживает обратные вызовы для применения этого алгоритма.
Вам просто нужно предоставить 2 обратных вызова методу usort . Первый — для получения соответствующего числа из объекта. А второй — записать округленное число обратно в полученный объект.
Обязательно передайте первый аргумент обратного вызова установщика в качестве ссылки, например. как в примере ниже:
&$item. В противном случае полученные данные сохранят свои первоначальные значения и не будут округляться.
$ objects = [
[ ' a ' => 18.562874251497007 ],
[ ' a ' => 20.958083832335326 ],
[ ' a ' => 18.562874251497007 ],
[ ' a ' => 19.161676646706585 ],
[ ' a ' => 22.75449101796407 ]
];
$ lr = new LargestRemainder ( $ objects );
$ lr -> setPrecision ( 2 );
print_r ( $ lr -> uround (
function ( $ item ) {
return $ item [ ' a ' ];
},
function (& $ item , $ value ) {
$ item [ ' a ' ] = $ value ;
}
));что приводит к:
Array
(
[0] => Array
(
[a] => 18.55
)
[1] => Array
(
[a] => 20.94
)
[2] => Array
(
[a] => 18.55
)
[3] => Array
(
[a] => 19.15
)
[4] => Array
(
[a] => 22.74
)
)