BCMath: Новая функция bcdivmod

Источник: «PHP 8.4: BCMath: New bcdivmod function»
bcdivmod может быть использован в случаях, когда необходимо получить частное и остаток от деления, и избавляет от необходимости вызывать функции bcdiv и bcmod по отдельности.

В PHP 8.4 в расширении BCMath представлена новая функция bcdivmod, делящая заданное число на заданный делитель и возвращающая как частное, так и остаток. Результат по сути идентичен вызову функций bcdiv и bcmod.

Возвращаемое значение — массив, в котором первое значение — частное от деления, а второе — остаток.

bcdivmod('42', '10');
// ["4", "2"]

Синопсис функции bcdivmod

/**
* @param string $num1 Делимое, как строка.
* @param string $num2 Делитель, как строка.
* @param int|null $scale Количество цифр после десятичного знака в остатке.
* Если это значение опущено или равно null, то по умолчанию будет использоваться
* значение, установленный глобально с помощью функции bcscale(), или резервное
* значение bcmath.scale INI (по умолчанию равно 0), если оно не было установлено.
*
* @return array
*/

function bcdivmod(string $num1, string $num2, ?int $scale = null): array {}

bcdivmod возвращает массив, содержащий частное (целое значения) в виде строки, и остаток — в виде строки, содержащей $scale количество знаков после запятой.

Примеры использования bcdivmod

bcdivmod("10", "10");
// ["1", "0"]
bcdivmod("10", "100");
// ["0", "10"]
// Использование значения по умолчанию bcmath.scale INI = 0
bcdivmod("8957", "5.43242");
// ["1648", "4"]
// Установка значения scale
bcdivmod("8957", "5.43242", 10);
// ["1648", "4.3718400000"]
bcdivmod("8957.5454312", "5.43242", 10);
// ["1648", "4.9172712000"]
bcdivmod("0", 42);
// ["0", "0"]

Условия ошибок bcdivmod

Функция bcdivmod имеет ту же семантику, что и другие функции расширения BCMath. Передача нечисловых значений вызывает исключение ValueError, а так как при объявлении типов параметров $num1 и $num2 они являются строковыми, то при использовании declare(strict_types=1) она следует стандартным правилам PHP о приведении типов и строгих типов.

Передача нуля в качестве делителя приводит к ошибке DivisionByZeroError:

bcdivmod("42", "0");
// DivisionByZeroError: Division by zero

Передача нечисловых строк или INF в $num1 или $num2 приводит к ошибке ValueError:

bcdivmod("42", "foobar");
// ValueError: bcdivmod(): Argument #2 ($num2) is not well-formed.

Влияние на обратную совместимость

bcdivmod — это новая функция, добавленная в расширение PHP 8.4 BCMath. Если не существует глобальной функции с таким же именем, это изменение не должно вызвать проблем с обратной совместимостью.

Следующий полифилл PHP использует функции bcdiv и bcmod и совместим с PHP 8.0 и более поздними версиями:

/**
* @param string $num1 Dividend, as a string.
* @param string $num2 Divisor, as a string.
* @param int|null $scale Number of digits after the decimal place in the
* remainder. If omitted or null, it will default to the scale set globally
* with the bcscale() function, or fallback to bcmath.scale INI value (default to 0) if this has not been set.
*
* @return array
*/

function bcdivmod(string $num1, string $num2, ?int $scale = null): array {
if (!is_numeric($num1)) {
throw new \ValueError('Argument #1 ($num1) is not well-formed');
}

if (!is_numeric($num2)) {
throw new \ValueError('Argument #2 ($num2) is not well-formed');
}

if ($num2 === '0') {
throw new \DivisionByZeroError('Division by zero');
}

return [
\bcdiv($num1, $num2, 0),
\bcmod($num1, $num2, $scale),
];
}

Комментарии


Дополнительные материалы

Предыдущая Статья

Разница между export default xxx и export {xxx as default}

Следующая Статья

PHP 8.4: MBString: База данных символов Юникода обновлена до версии 16