Глава 92 · С нуля до полного API
BCMath: точные десятичные расчёты и Number
Десятичные строки, масштаб, все функции и методы BCMath, округление и реальные границы денежных расчётов.
Задача: получить 0.30 без двоичного приближения
Десятичная сумма без скрытого перехода в float
Строки 0.10 и 0.20 передаются в вычисление как точные десятичные записи.
- Вход: строки
Проверенные значения '0.10' и '0.20', без предварительного float-преобразования.
- bcadd(..., 2)
Вычисление в десятичной арифметике; scale задаёт два знака после точки.
- Строка '0.30'
Результат сохраняет десятичную запись. Это ещё не локализованный текст цены.
- Политика денег
Единицы, допустимый диапазон, округление и распределение копеек определяет приложение.
Scale не равен округлению. Вход из формы проверяют отдельно: библиотека допускает некоторые записи, которые не подходят для цены.
Магазин складывает десятичные суммы, интеграция передаёт цену строкой, прибор сохраняет много знаков после точки. В PHP float хранит двоичное приближение; BCMath вычисляет по десятичным строкам. Результат первого вызова — строка 0.30, которую можно сохранить без предварительного float.
bcadd — готовая функция сложения. (...) ограничивают её входы, запятая разделяет их. '0.10' и '0.20' — строки, кавычки не входят в число. Третий аргумент 2 оставляет два знака после точки. echo печатает результат; ; завершает команду, "\n" переводит строку.
- Текст 0.10 и текст 0.20
- bcadd разбирает десятичные цифры
- Складывает без промежуточного float
- Возвращает текст 0.30; echo печатает
<?php
echo bcadd('0.10', '0.20', 2), "\n";
Ожидаемый результат
0.30
Число знаков после точки называется scale. Это модель цифр, не буквальная коробка с бесконечной памятью: время и память ограничены.
Для целого количества копеек часто подходит обычный int при контроле диапазона. BCMath нужен, когда важна десятичная дробь, много разрядов или выход за диапазон int. Он не выбирает валюту, правила налога, этап округления и допустимую точность входного измерения. Что такое переменная; Чем отличаются int, float и string.
Проверить расширение, версию и значение по умолчанию
BCMath входит в исходники PHP, но в Unix-сборке требуется --enable-bcmath либо соответствующий пакет дистрибутива. Официальная Windows-сборка имеет встроенную поддержку; не требуется искать отдельную BCMath DLL. CLI и веб-сервер могут использовать разные сборки и ini: проверяйте тот процесс, где выполняется приложение. Общая установка — подготовка PHP.
extension_loaded проверяет наличие расширения; function_exists и class_exists — доступность конкретного API. var_dump показывает true/false. Операторы ниже изучаются отдельно: здесь лишь безопасная диагностика без изменения сервера.
- Текущий процесс PHP
- Есть bcmath?
- Есть bcround и BcMath\Number?
- Если да — доступна ветка PHP 8.4+
<?php
var_dump(extension_loaded('bcmath'));
var_dump(function_exists('bcround'));
var_dump(class_exists(BcMath\Number::class));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
Вывод относится к проверенному PHP 8.5.11. На PHP 8.2/8.3 первые базовые функции могут существовать, а Number, bcdivmod и три функции округления ещё отсутствуют.
| Настройка | Договор |
|---|---|
| bcmath.scale | По умолчанию "0", режим INI_ALL. Определяет scale процедурных функций при null/пропуске. bcscale читает/меняет значение. |
| Явный scale | Локально определяет конкретный вызов, удобен для библиотек и workers. |
| Number | С PHP 8.4, независим от bcmath.scale; масштаб задаётся методом либо вычисляется из входов. |
В этой ветке нет отдельной внешней библиотеки, каталога ресурсов или собственных констант режимов. RoundingMode — общий встроенный enum, уже описанный в RoundingMode.
Числовая строка не равна любому тексту из формы
BCMath принимает десятичную точку, необязательный знак и цифры; научную запись E, пробелы, запятую, INF/NAN он не понимает. Официальная грамматика /^[+-]?[0-9]*(\.[0-9]*)?$/ допускает даже отсутствие цифр. В PHP 8.5.11 пустая строка, знак или точка дают ноль: это допустимость низкоуровневого API, а не хорошая проверка цены.
До PHP 8.0 превращение float в строку могло зависеть от региональной десятичной запятой. Сейчас это уже не так, но двоичная погрешность и возможность E-записи остаются. JSON-число могло стать float ещё при json_decode: точное десятичное поле передают строкой по контракту. JSON при интеграции.
$input = ... сохраняет строку; try/catch ловит неверный вход. Затем вводим preg_match: он проверяет формат; \A/\z ограничивают всю строку, [0-9] — цифра, {1,9} — 1–9 повторов, ? делает группу необязательной. Это строгая политика именно нашей формы, не описание всей BCMath-грамматики. Как читать регулярное выражение.
- Строка 12.30
- Проверяем обязательность, длину и два десятичных места
- Только затем bcadd(input,0,2)
- Каноническая цена 12.30
<?php
echo bcadd('', '0', 2), "\n";
try { bcadd('1e-3', '0', 3); }
catch (ValueError $error) { echo "Экспонента не поддерживается\n"; }
Ожидаемый результат
0.00
Экспонента не поддерживается
Отсутствие ValueError для пустой строки не доказывает, что пользователь заполнил поле.
Теперь вынесем проверку в function normalizedPrice($input) { ... }: вызов передаёт текст локальному параметру, return возвращает строку либо null при отказе. if проверяет условие; ! означает «не», || — «или». foreach по очереди берёт строки списка. условие ? A : B выбирает, что вывести. Определение, вызов и результат; Условия и циклы.
<?php
function normalizedPrice($input) {
if (!is_string($input) || strlen($input) > 12 ||
preg_match('/\A(?:0|[1-9][0-9]{0,8})(?:\.[0-9]{1,2})?\z/', $input) !== 1) {
return null;
}
return bcadd($input, '0', 2);
}
foreach (['12.3', '', '12,30', '1e3', '12.345', '-1', '0'] as $input) {
$price = normalizedPrice($input);
echo $price === null ? 'Ошибка' : $price;
echo "\n";
}
Ожидаемый результат
12.30
Ошибка
Ошибка
Ошибка
Ошибка
Ошибка
0.00
Функция принимает неотрицательную цену с максимум девятью целыми и двумя дробными разрядами; ноль разрешён сознательно. ! отрицает, || означает «или», !==1 требует успешного совпадения, null обозначает отказ. В реальной форме проверяют также HTTP-метод, CSRF и вывод ошибки: приём формы.
Не исправляйте молча «1,234»: это может быть десятичная дробь или тысячи. Не восстанавливайте точный исходник через sprintf после float: это только новое представление уже приближённого значения. Условия валюты/диапазона проверяйте отдельно.
Масштаб, усечение и момент округления
scale считает знаки после точки, а не значащие цифры всей записи. Большинство bc-функций усекают лишнее к нулю. Введём переменную $raw для промежуточного результата; bcround затем выбирает ближайшие сотые. Нужные функции доступны с PHP 8.4. На старших этапах функция не может вернуть цифры, которые предыдущий вызов уже отбросил.
- 19.99 × 0.075
- bcmul с scale 5 → 1.49925
- bcround до сотых
- 1.50; преждевременное усечение дало бы 1.49
<?php
$raw = bcmul('19.99', '0.075', 5);
echo $raw, "\n";
echo bcmul('19.99', '0.075', 2), "\n";
echo bcround($raw, 2), "\n";
Ожидаемый результат
1.49925
1.49
1.50
Произведение конечных дробей имеет не больше суммы их дробных разрядов. Для деления/корня такого простого конечного предела нет: нужен договор допустимой погрешности.
<?php
$oneLine = bcround('0.335', 2);
$sumRoundedLines = bcmul($oneLine, '3', 2);
$roundedTotal = bcround(bcmul('0.335', '3', 3), 2);
echo $sumRoundedLines, "\n", $roundedTotal, "\n";
Ожидаемый результат
1.02
1.01
Оба алгоритма точны в своих правилах, но округляют на разных этапах. В заказе надо хранить и объяснять выбранное правило; нельзя произвольно комбинировать уже округлённые строки с другим способом подсчёта итога.
Технический предел scale — 2147483647, но миллиард знаков не является разумной настройкой веб-запроса. Ограничьте длину поля, scale, показатель степени и число операций. Функции не становятся безопасными для произвольных входов лишь из-за слова «точность». Измерять стоимость вычислений.
Все восемь правил RoundingMode
Enum задаёт конечный набор именованных вариантов. Запись RoundingMode::HalfEven выбирает один вариант; RoundingMode::cases() возвращает их список. Четыре Half-режима отличаются только на точной половине, остальные четыре задают направление для любой ненулевой удаляемой части. Каноническая карточка: RoundingMode.
| Вариант | Правило | 2.5 / −2.5 до целого |
|---|---|---|
| HalfAwayFromZero | Ближайшее; ровно половина от нуля | 3 / -3 |
| HalfTowardsZero | Ближайшее; ровно половина к нулю | 2 / -2 |
| HalfEven | Ближайшее; половина к чётной сохраняемой цифре | 2 / -2 |
| HalfOdd | Ближайшее; половина к нечётной сохраняемой цифре | 3 / -3 |
| TowardsZero | Всегда к нулю | 2 / -2 |
| AwayFromZero | Всегда от нуля при ненулевой удаляемой части | 3 / -3 |
| NegativeInfinity | В сторону −∞ | 2 / -3 |
| PositiveInfinity | В сторону +∞ | 3 / -2 |
- −2.5
- HalfEven: ближайшие целые −2 и −3
- При половине выбираем чётное −2
- bcround возвращает строку −2
<?php
foreach (RoundingMode::cases() as $mode) {
echo $mode->name, ': ', bcround('2.5', 0, $mode), ' / ', bcround('-2.5', 0, $mode), "\n";
}
Ожидаемый результат
HalfAwayFromZero: 3 / -3
HalfTowardsZero: 2 / -2
HalfEven: 2 / -2
HalfOdd: 3 / -3
TowardsZero: 2 / -2
AwayFromZero: 3 / -3
NegativeInfinity: 2 / -3
PositiveInfinity: 3 / -2
foreach берёт варианты по одному, ->name читает название. HalfAwayFromZero — default. Это тот же enum, что у round, но bcround требует enum и не принимает старые int-константы PHP_ROUND_*.
Округление цены не является юридическим правилом расчёта налога: требуемую политику выбирает доменная спецификация. Полезное упражнение: замените 2.5 на 2.1. HalfEven и TowardsZero всё ещё совпадут на положительном входе, а HalfAwayFromZero и AwayFromZero уже разойдутся.
Тот же расчёт через Number: что хранит объект
Функции удобны, когда данные уже строки. Number (PHP 8.4+) хранит строковое значение и масштаб вместе, возвращая новое число после каждой операции. new создаёт объект, -> вызывает его метод. В цепочке результат первого метода становится получателем второго. Number не знает, что такое рубль, количество или НДС: это контейнер числа, а не целый класс денег.
| Операция без явного scale | Правило Number |
|---|---|
| add, sub, mod | Максимальный scale двух входов. |
| mul | Сумма scale входов. |
| div, sqrt | Исходный scale, по необходимости ещё до 10 знаков; лишние нули расширения убираются. |
| pow | Положительная степень: scale основания × показатель. Ноль: 0. Отрицательная: правило расширения как у div. |
| powmod | 0. |
| divmod | Частное 0, остаток — максимум входов. |
| compare | Все разряды при null. |
| ceil, floor | 0. |
| round | Положительная precision либо 0. |
- price = Number(12.30)
- price->mul(3) → отдельный subtotal 36.90
- subtotal->add(2.10) → отдельный total 39.00
- price по-прежнему 12.30
<?php
$price = new BcMath\Number('12.30');
$subtotal = $price->mul(3);
$total = $subtotal->add('2.10');
echo $price, "\n", $subtotal, "\n", $total, "\n";
Ожидаемый результат
12.30
36.90
39.00
Никакое ООП-обёртывание не делает вычисление автоматически быстрее. Польза здесь — связанное значение/масштаб и локальное правило методов. Для PHP 8.2/8.3 такой же результат дают bcmul и bcadd с явным scale.
Не смешивайте методы с неявным int/float cast. Арифметика Number поддерживает + − * / % **; сравнения == != < <= > >= <=> числовые, === проверяет идентичность. Нулевой Number в bool — false. Подробности и пограничные случаи: BcMath\Number, BcMath\Number::compare.
Упражнение: счёт, возврат и неизрасходованная копейка
Задача: товар стоит 19.90, куплено 3 штуки, доставка 4.30. Получить 64.00, вычесть возврат 19.90 и разделить остаток между тремя получателями без потери копейки. Валюта общая, входы уже проверены; правило распределения — первые участники получают по дополнительной копейке до исчерпания остатка.
Функция splitCents получает сумму и количество людей, а return отдаёт список долей. bcdivmod возвращает две строки — целое частное и остаток; запись [$share, $rest] = ... раскладывает их по переменным. $parts[] = ... добавляет элемент массива; for задаёт старт, условие и шаг счётчика, ++ увеличивает его на один. ?/: выбирают значение по условию, implode соединяет список для вывода. Счётчики здесь малы и безопасно помещаются в int. Циклы и условия.
- 19.90 × 3 + 4.30 = 64.00
- Возврат 19.90 → 44.10
- Перевод единиц: 4410 копеек / 3
- Три доли по 1470 → 14.70
<?php
function splitCents($cents, $people) {
[$share, $rest] = bcdivmod($cents, (string) $people, 0);
$parts = [];
for ($index = 0; $index < $people; $index++) {
$extra = bccomp((string) $index, $rest, 0) < 0 ? '1' : '0';
$parts[] = bcdiv(bcadd($share, $extra, 0), '100', 2);
}
return $parts;
}
$total = bcadd(bcmul('19.90', '3', 2), '4.30', 2);
$remaining = bcsub($total, '19.90', 2);
echo $total, "\n", $remaining, "\n";
echo implode(', ', splitCents(bcmul($remaining, '100', 0), 3)), "\n";
echo implode(', ', splitCents('1000', 3)), "\n";
Ожидаемый результат
64.00
44.10
14.70, 14.70, 14.70
3.34, 3.33, 3.33
Контракт splitCents: неотрицательное целое число копеек строкой и положительное небольшое people. В форме дополнительно проверяют их до вызова. 10.00 показывает распределение одной оставшейся копейки; порядок получателей должен быть согласован.
Продолжение: сохраните исходную цену, валюту, этап округления и итог операции; обновляйте остаток в транзакции БД. BCMath не обеспечивает конкурентную блокировку, авторизацию или идемпотентность повторного платежного запроса.
Полный API BCMath: выбрать функцию или метод
Все функции и методы официальной ветки находятся ниже. Аналогичные задачи связывают процедурный и объектный API; различия default scale указаны в карточках.
| Нужный результат | Вход |
|---|---|
| Сумма/разность/произведение | bcadd, bcsub, bcmul |
| Частное/остаток/оба | bcdiv, bcmod, bcdivmod |
| Сравнение и настройки | bccomp, bcscale |
| Степень/модуль/корень | bcpow, bcpowmod, bcsqrt |
| Округление | bcceil, bcfloor, bcround |
| Объектное значение | BcMath\Number |
| Метод Number | Назначение |
|---|---|
BcMath\Number::add | Сложить сумму заказа с доставкой. |
BcMath\Number::ceil | Получить ближайшее целое не меньше исходного. |
BcMath\Number::compare | Проверить числовое равенство или порядок, не привязываясь к идентичности объектов. |
BcMath\Number::__construct | Создать проверенное десятичное число из строки или целого. |
BcMath\Number::div | Разделить число и сохранить достаточные дополнительные разряды в пределах автоматического правила. |
BcMath\Number::divmod | Разделить количество на полные группы и получить остаток объектами Number. |
BcMath\Number::floor | Получить ближайшее целое не больше исходного. |
BcMath\Number::mod | Найти остаток длины после целого количества отрезков. |
BcMath\Number::mul | Умножить тариф на количество или коэффициент. |
BcMath\Number::pow | Возвести число в целую степень с автоматическим масштабом результата. |
BcMath\Number::powmod | Вычислить модульную степень, не материализуя полную огромную степень. |
BcMath\Number::round | Получить новое число, округлённое до выбранного десятичного разряда. |
BcMath\Number::__serialize | Подготовить внутренние данные Number для штатного PHP serialize(). |
BcMath\Number::sqrt | Получить неотрицательный квадратный корень и управлять числом его разрядов. |
BcMath\Number::sub | Вычесть возврат, сохранив исходную сумму для журнала. |
BcMath\Number::__toString | Получить исходную десятичную строку для текста или явной передачи в другой интерфейс. |
BcMath\Number::__unserialize | Восстановить новый Number из состояния, созданного сериализацией. |
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
bcaddСложить цены, сохранив десятичные разряды.
bcadd(string $num1, string $num2, ?int $scale = null): stringСложить цены, сохранив десятичные разряды.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. foreach ($items as $item) проходит список; форма $key => $value получает также ключ. [...] создаёт массив; [$a, $b] = ... раскладывает два результата по переменным, $data["value"] читает элемент по ключу. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num1, num2 | Левый и правый операнды в десятичной строковой записи. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. |
| Возврат | Строка: сумма. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. |
| Версия | PHP 4+; nullable scale с 8.0 |
- 19.90 и 0.10 — строки
- bcadd(..., 2) складывает значения
- Возвращает строку 20.00
<?php
echo bcadd('19.90', '0.10', 2), "\n";
echo bcadd('999999999999999999999', '1', 0), "\n";
Ожидаемый результат
20.00
1000000000000000000000
Первый результат можно отправить в десятичное поле БД. Второй не помещается в обычный int: кавычки сохраняют все цифры.
<?php
function cartSum($prices) {
$total = '0.00';
foreach ($prices as $price) {
$total = bcadd($total, $price, 2);
}
return $total;
}
echo cartSum(['12.40', '0.60', '7.00']), "\n";
Ожидаемый результат
20.00
Все цены уже проверены и выражены в одной валюте с двумя знаками. Начальное строковое 0.00 задаёт понятный формат, а явный scale не зависит от стороннего кода.
Практическая граница. При scale 2 промежуточные тысячные теряются на каждом сложении. Если они значимы, храните их до выбранного этапа округления. Большие идентификаторы не нужно складывать лишь потому, что они состоят из цифр.
Соседние инструменты: bcsub, bcround, BcMath\Number::add. Выбор по задаче.
bcsubВычесть возврат или оплату из суммы счёта.
bcsub(string $num1, string $num2, ?int $scale = null): stringВычесть возврат или оплату из суммы счёта.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. if (условие) выбирает действие; === сравнивает значение и тип, !== проверяет их различие. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num1, num2 | Левый и правый операнды в десятичной строковой записи. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. |
| Возврат | Строка: разность num1 − num2. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. |
| Версия | PHP 4+; nullable scale с 8.0 |
- Счёт 50.00
- Вычитаем оплату 12.35
- Остаток 37.65
<?php
echo bcsub('50.00', '12.35', 2), "\n";
echo bcsub('0', '0.019', 2), "\n";
Ожидаемый результат
37.65
-0.01
Усечение идёт к нулю: −0.019 превращается в −0.01, а не −0.02. Второе значение показывает, почему scale не равен floor.
<?php
function debit($balance, $amount) {
if (bccomp($amount, $balance, 2) === 1) {
return 'Недостаточно средств';
}
return bcsub($balance, $amount, 2);
}
echo debit('25.00', '10.20'), "\n";
echo debit('25.00', '30.00'), "\n";
Ожидаемый результат
14.80
Недостаточно средств
Учебные входы неотрицательны и имеют два знака. В БД проверка и списание должны быть одной защищённой транзакцией: арифметика сама не предотвращает две одновременные покупки.
Практическая граница. Порядок операндов существенен. Отрицательный результат допустим математически, но не всегда допустим для остатка товара/баланса. Правила задачи проверяются отдельно.
Соседние инструменты: bcadd, bcround, BcMath\Number::sub. Выбор по задаче.
bcmulПолучить стоимость количества или сумму комиссии.
bcmul(string $num1, string $num2, ?int $scale = null): stringПолучить стоимость количества или сумму комиссии.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. RoundingMode::HalfEven — именованный вариант правила округления, а не строка или вызов. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num1, num2 | Левый и правый операнды в десятичной строковой записи. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. |
| Возврат | Строка: произведение. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. |
| Версия | PHP 4+; nullable scale с 8.0; заполнение нулями по scale с 7.3 |
- Тариф 12.35
- Умножаем на количество 3
- Получаем строку 37.05
<?php
echo bcmul('12.35', '3', 2), "\n";
echo bcmul('4', '5', 2), "\n";
Ожидаемый результат
37.05
20.00
Количество тоже строка. Начиная с PHP 7.3 результат дополняется до scale; в более старых версиях хвостовые нули могли отсутствовать.
<?php
$commission = bcmul('19.99', '0.075', 5);
echo $commission, "\n";
echo bcround($commission, 2, RoundingMode::HalfAwayFromZero), "\n";
Ожидаемый результат
1.49925
1.50
PHP 8.4+. 2 + 3 дробных разряда входов дают до пяти у точного произведения. Если сразу использовать scale 2, получится 1.49 и утраченный разряд уже нельзя восстановить округлением.
Практическая граница. Для целых копеек int бывает проще, пока нет переполнения и дробных частей копейки. Умножение длинных строк и большой scale требуют времени и памяти: ограничивайте внешние размеры и измеряйте свой расчёт.
Соседние инструменты: bcdiv, bcround, BcMath\Number::mul. Выбор по задаче.
bcdivРазделить сумму на количество, не переходя к двоичному float.
bcdiv(string $num1, string $num2, ?int $scale = null): stringРазделить сумму на количество, не переходя к двоичному float.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. if (условие) выбирает действие; === сравнивает значение и тип, !== проверяет их различие. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num1 | Делимое. |
| num2 | Делитель; числовой ноль запрещён. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. |
| Возврат | Частное строкой. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. Деление на ноль → DivisionByZeroError (с PHP 8.0; ранее null). |
| Версия | PHP 4+ |
- 10.00 делим на 3
- Сохраняем два знака без округления
- Возврат 3.33
<?php
echo bcdiv('10.00', '3', 2), "\n";
echo bcdiv('-10', '3', 0), "\n";
Ожидаемый результат
3.33
-3
Отрицательное частное также усекается к нулю. Это не распределение всей суммы: три раза 3.33 дают 9.99.
<?php
function averagePrice($total, $count) {
if (bccomp($count, '0', 0) <= 0) {
return 'Количество должно быть положительным';
}
return bcdiv($total, $count, 4);
}
echo averagePrice('25.00', '8'), "\n";
echo averagePrice('25.00', '0'), "\n";
Ожидаемый результат
3.1250
Количество должно быть положительным
Здесь count уже проверенное целое. Для общего десятичного делителя сравнение со scale 0 непригодно: 0.5 оно считает нулём.
<?php
try { bcdiv('1', '-0.00', 2); }
catch (DivisionByZeroError $error) { echo "Делитель равен нулю\n"; }
Ожидаемый результат
Делитель равен нулю
Разные текстовые формы нуля не обходят математическое ограничение.
Практическая граница. Ограниченный scale не представляет бесконечную периодическую дробь точно. Для распределения копеек понадобятся целое частное и остаток, а не одинаковая усечённая доля.
Соседние инструменты: bcdivmod, bcmul, BcMath\Number::div. Выбор по задаче.
bcmodНайти остаток после целого количества порций, включая дробные исходные величины.
bcmod(string $num1, string $num2, ?int $scale = null): stringНайти остаток после целого количества порций, включая дробные исходные величины.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num1 | Делимое; ненулевой остаток имеет его знак. |
| num2 | Делитель, не ноль. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. |
| Возврат | Остаток строкой. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. При нулевом делителе DivisionByZeroError. |
| Версия | PHP 4+; дробные операнды и scale с 7.2; nullable и DivisionByZeroError с 8.0 |
- 17.55 литра
- Четыре ёмкости по 4.2: 16.8
- Остаток 0.75
<?php
echo bcmod('17.55', '4.2', 2), "\n";
echo bcmod('-17.55', '4.2', 2), "\n";
Ожидаемый результат
0.75
-0.75
С PHP 7.2 дробные части входов не отбрасываются, тогда же добавлен scale. Оператор % преобразует обычные операнды в целые; fmod работает с float.
<?php
function looseItems($items, $packSize) {
return bcmod($items, $packSize, 0);
}
echo looseItems('100000000000000000005', '12'), "\n";
try { looseItems('10', '0'); }
catch (DivisionByZeroError $error) { echo "Размер упаковки не может быть нулём\n"; }
Ожидаемый результат
9
Размер упаковки не может быть нулём
Для целых количеств scale 0 достаточен; входной размер ещё нужно проверить на положительность.
Практическая граница. Отрицательный остаток не является автоматически номером циклической ячейки 0…m−1. Для положительного m нормализуют при необходимости bcmod(bcadd(r,m),m); это отдельное правило задачи.
Соседние инструменты: bcdivmod, bcpowmod, BcMath\Number::mod. Выбор по задаче.
bcdivmodПолучить целое частное и остаток одним вызовом: например, разделить 1000 копеек на три части.
bcdivmod(string $num1, string $num2, ?int $scale = null): arrayПолучить целое частное и остаток одним вызовом: например, разделить 1000 копеек на три части.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. [...] создаёт массив; [$a, $b] = ... раскладывает два результата по переменным, $data["value"] читает элемент по ключу. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num1, num2 | Делимое и ненулевой делитель строками. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. Здесь он относится к остатку: частное всегда целое. |
| Возврат | Индексированный массив [частное-строка, остаток-строка]. Частное усекается к нулю; знак ненулевого остатка совпадает с делимым. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. Ноль в num2 → DivisionByZeroError. |
| Версия | PHP 8.4+ |
- 1000 копеек / 3
- Целое частное 333
- Остаток 1 копейка
<?php
[$share, $rest] = bcdivmod('1000', '3', 0);
echo $share, "\n", $rest, "\n";
Ожидаемый результат
333
1
Квадратные скобки слева присваивают первый и второй элементы двум переменным. Полученные строки сохраняют точность.
<?php
[$share, $rest] = bcdivmod('1000', '3', 0);
$parts = [$share, $share, $share];
$parts[0] = bcadd($parts[0], $rest, 0);
echo implode(', ', $parts), "\n";
echo bcadd(bcadd($parts[0], $parts[1], 0), $parts[2], 0), "\n";
Ожидаемый результат
334, 333, 333
1000
Для именно трёх долей и остатка 1 выбран первый участник. В общей системе надо явно задать порядок распределения нескольких копеек, а не отдавать весь остаток одному без договора.
<?php
[$q, $r] = bcdivmod('-17.55', '4.2', 1);
echo $q, "\n", $r, "\n";
Ожидаемый результат
-4
-0.7
Истинный остаток −0.75 усечён до −0.7: при недостаточном scale равенство a = q*b+r перестаёт быть точным.
Практическая граница. Для точного восстановления входа выбирайте достаточный scale остатка. На PHP 8.2/8.3 вызывайте bcdiv(a,b,0) и bcmod(a,b,scale) отдельно.
Соседние инструменты: bcdiv, bcmod, BcMath\Number::divmod. Выбор по задаче.
bccompСравнить значения десятичных строк, даже если их текстовый формат различается.
bccomp(string $num1, string $num2, ?int $scale = null): intСравнить значения десятичных строк, даже если их текстовый формат различается.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. if (условие) выбирает действие; === сравнивает значение и тип, !== проверяет их различие. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num1, num2 | Левое и правое сравниваемые числа. |
| scale | Глубина сравнения после точки, 0…2147483647; лишние знаки игнорируются. null берёт bcscale()/INI. |
| Возврат | int: −1 (левое меньше), 0 (равны в выбранном масштабе), 1 (левое больше). |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. |
| Версия | PHP 4+ |
- 12.345 и 12.349
- Сравнение в scale 2
- Оба 12.34 → результат int 0
<?php
var_dump(bccomp('12.345', '12.349', 2));
var_dump(bccomp('12.345', '12.349', 3));
var_dump(bccomp('-0.00', '+0.000', 3));
Ожидаемый результат
int(0)
int(-1)
int(0)
На проверенном PHP 8.5.11 отрицательная запись нуля равна положительной. Старые обсуждения ошибки нельзя переносить на современный результат.
<?php
function deliveryLabel($total) {
if (bccomp($total, '1500.00', 2) >= 0) {
return 'Бесплатно';
}
return 'По тарифу';
}
echo deliveryLabel('1499.99'), "\n";
echo deliveryLabel('1500.0'), "\n";
Ожидаемый результат
По тарифу
Бесплатно
Уже проверенные суммы имеют не более двух знаков. Результат сравнения числовой: проверка if (bccomp(...)) означала бы «не равны», а не «больше».
Практическая граница. Строковое === сравнивает запись, а преобразование в float теряет точность. Выберите масштаб по данным; для Number::compare(null) используются все разряды.
Соседние инструменты: BcMath\Number::compare, bcscale. Выбор по задаче.
bcscaleЗадать значение по умолчанию для процедурных вычислений или узнать текущее.
bcscale(?int $scale = null): intЗадать значение по умолчанию для процедурных вычислений или узнать текущее.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| scale | null/пропуск: прочитать. Целое 0…2147483647: установить для последующих bc-функций с неуказанным/null scale. |
| Возврат | При установке — предыдущее значение, при чтении — текущее. |
| Отказы | Недопустимый диапазон → ValueError; неподходящий тип → TypeError. |
| Версия | PHP 4+; getter и возврат старого значения с 7.3; nullable с 8.0 |
До PHP 7.3 параметр был обязательным, а setter возвращал true. bcmath.scale по умолчанию 0 и имеет режим INI_ALL.
- Сначала задаём scale 2
- Следующее деление без scale
- 1 / 8 → 0.12
<?php
bcscale(2);
echo bcscale(), "\n";
echo bcdiv('1', '8'), "\n";
echo bcscale(4), "\n";
echo bcdiv('1', '8'), "\n";
Ожидаемый результат
2
0.12
2
0.1250
Setter вернул прежние 2, затем вычисление использовало 4. Отдельный процесс примера не меняет настройки других запусков.
<?php
bcscale(2);
function legacyReport() {
$old = bcscale(4);
try { return bcdiv('1', '8'); }
finally { bcscale($old); }
}
echo legacyReport(), "\n";
echo bcscale(), "\n";
echo (new BcMath\Number('1'))->div(8), "\n";
Ожидаемый результат
0.1250
2
0.125
finally восстанавливает настройку и при return/исключении. Последний вызов PHP 8.4+ показывает независимость Number от глобального scale.
Практическая граница. Скрытая настройка усложняет библиотеки и долгоживущие workers: предпочтительны явные scale. Это не региональная точность, не количество значащих цифр и не правило округления.
Соседние инструменты: bcdiv, BcMath\Number. Выбор по задаче.
bcpowВозвести десятичное основание в целую степень: накопление коэффициента за несколько периодов.
bcpow(string $num, string $exponent, ?int $scale = null): stringВозвести десятичное основание в целую степень: накопление коэффициента за несколько периодов.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Десятичное основание. |
| exponent | Целочисленное значение строкой, без ненулевой дробной части. Диапазон платформы как минимум −2147483648…2147483647; в реализации используется C long, поэтому его предел нельзя автоматически приравнять к PHP_INT_MAX на любой ОС. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. |
| Возврат | Степень строкой; отрицательный показатель означает обратное значение. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. Дробный/слишком большой показатель → ValueError. 0 в отрицательной степени → DivisionByZeroError с 8.4. |
| Версия | PHP 4+ |
- Коэффициент 1.05
- Два периода: 1.05 × 1.05
- Результат 1.1025
<?php
echo bcpow('1.05', '2', 4), "\n";
echo bcpow('2', '0', 2), "\n";
echo bcpow('2', '-3', 3), "\n";
Ожидаемый результат
1.1025
1.00
0.125
Показатель 0 даёт единицу; отрицательный не означает отрицательный результат.
<?php
function projectedTotal($initial, $factor, $periods) {
return bcmul($initial, bcpow($factor, $periods, 6), 6);
}
echo projectedTotal('1000.00', '1.02', '3'), "\n";
try { bcpow('9', '0.5', 2); }
catch (ValueError $error) { echo "Показатель должен быть целым\n"; }
Ожидаемый результат
1061.208000
Показатель должен быть целым
Это арифметическая модель с постоянным коэффициентом, не прогноз. Для квадратного корня есть bcsqrt; прежнее молчаливое усечение дробного показателя заменено ValueError с PHP 8.0.
<?php
try { bcpow('0', '-1', 2); }
catch (DivisionByZeroError $error) { echo "Обратного нулю нет\n"; }
Ожидаемый результат
Обратного нулю нет
PHP 8.4+: раньше этот случай возвращал 0. Масштаб результата заполняется нулями с PHP 7.3.
Практическая граница. Размер результата быстро растёт с показателем. Для огромного показателя по модулю используйте bcpowmod, а не сначала полную степень. Оператор ^ в PHP — XOR, степень записывается **.
Соседние инструменты: bcpowmod, bcsqrt, BcMath\Number::pow. Выбор по задаче.
bcpowmodВычислить остаток большой степени, не создавая сначала всю огромную степень.
bcpowmod(string $num, string $exponent, string $modulus, ?int $scale = null): stringВычислить остаток большой степени, не создавая сначала всю огромную степень.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Целое основание строкой. |
| exponent | Неотрицательное целое строкой. |
| modulus | Ненулевое целое строкой. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. |
| Возврат | Строка: num в степени exponent по modulus. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. Ненулевая дробная часть любого из трёх чисел или отрицательный exponent → ValueError; modulus 0 → DivisionByZeroError. |
| Версия | PHP 5+ |
- 7 в степени 4
- Вычисление с сокращением по модулю 13
- Остаток 9
<?php
echo bcpowmod('7', '4', '13', 0), "\n";
echo bcpowmod('-7', '3', '13', 2), "\n";
Ожидаемый результат
9
-5.00
Алгоритм быстрого возведения сокращает промежуточные результаты. Отрицательное основание может дать отрицательный остаток; это не автоматическая нормализация 0…m−1.
<?php
echo bcpowmod('2', '1000', '97', 0), "\n";
try { bcpowmod('2', '-1', '97', 0); }
catch (ValueError $error) { echo "Отрицательный показатель запрещён\n"; }
Ожидаемый результат
36
Отрицательный показатель запрещён
Пример иллюстрирует модульную арифметику. Это не готовая криптография: здесь не обещаются постоянное время исполнения, безопасные ключи или протокол.
Практическая граница. Для целых положительных входов соответствует bcmod(bcpow(...),modulus), но избегает роста полной степени. Не путайте отрицательную степень с модульным обратным: данный API её не вычисляет. С PHP 8.0 отрицательный exponent/нулевой modulus дают исключения вместо false; scale допускает null.
Соседние инструменты: bcpow, bcmod, BcMath\Number::powmod. Выбор по задаче.
bcsqrtПолучить квадратный корень для расчёта стороны или нормирования величины.
bcsqrt(string $num, ?int $scale = null): stringПолучить квадратный корень для расчёта стороны или нормирования величины.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Неотрицательная десятичная строка. |
| scale | Число знаков после точки: целое от 0 до 2147483647, технический предел не обещает доступной памяти. Явный scale усекает лишние дробные разряды к нулю и дополняет недостающие нулями. null/пропуск: текущее bcscale(), исходно bcmath.scale (обычно 0). Это не округление до ближайшего. |
| Возврат | Неотрицательный квадратный корень строкой. |
| Отказы | Неверная десятичная запись или scale вне диапазона → ValueError; несовместимый тип → TypeError. Операнды передаются строками, без пробелов, запятой, E-экспоненты, INF/NAN. Данные формы проверяют строже допустимой BCMath-грамматики. Отрицательный num → ValueError. |
| Версия | PHP 4+ |
- Площадь 6.25
- bcsqrt с двумя знаками
- Сторона 2.50
<?php
echo bcsqrt('6.25', 2), "\n";
echo bcsqrt('3', 5), "\n";
Ожидаемый результат
2.50
1.73205
Первый корень представим точно. Второй ограничен пятью знаками: произвольная точность не означает бесконечную память.
<?php
function squareSide($area) {
return bcsqrt($area, 3);
}
echo squareSide('12.25'), "\n";
try { squareSide('-1'); }
catch (ValueError $error) { echo "Площадь не может быть отрицательной\n"; }
Ожидаемый результат
3.500
Площадь не может быть отрицательной
Для отрицательного реального числа квадратный корень вне действительной области; комплексные числа BCMath не представляет.
Практическая граница. Для округления корня до заданного разряда нужен запас вычисленных цифр и согласованная политика погрешности. С PHP 8.0 плохая строка/отрицательное число — ValueError вместо warning; отрицательный scale больше не превращается молча в 0.
Соседние инструменты: bcpow, BcMath\Number::sqrt, bcround. Выбор по задаче.
bcceilОкруглить десятичную строку до целого в сторону +∞.
bcceil(string $num): stringОкруглить десятичную строку до целого в сторону +∞.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Число в десятичной строковой записи; scale не передаётся. |
| Возврат | Строка целого числа без дробной части. |
| Отказы | Плохая строка → ValueError; несовместимый тип → TypeError. |
| Версия | PHP 8.4+ |
- Вход 2.1
- bcceil выбирает целое в сторону +∞
- Возврат 3
<?php
echo bcceil('2.1'), "\n";
echo bcceil('-2.1'), "\n";
Ожидаемый результат
3
-2
Направление выбирается на числовой прямой. «Вверх» не означает увеличить модуль отрицательного числа.
<?php
$ratio = bcdiv('17', '4', 2);
echo bcceil($ratio), "\n";
Ожидаемый результат
5
17 штук не помещаются в четыре упаковки по четыре. Здесь частное 4.25 конечно и scale 2 сохраняет его полностью; произвольно усечённое почти целое частное могло бы дать неверное ceil. Для целых количеств надёжнее bcdivmod плюс проверка остатка.
Практическая граница. Не зависит от bcscale. Для двух знаков после точки используйте bcround с соответствующим RoundingMode. Не переводите результат в int без проверки диапазона.
Соседние инструменты: bcfloor, bcround, BcMath\Number::ceil. Выбор по задаче.
bcfloorОкруглить десятичную строку до целого в сторону −∞.
bcfloor(string $num): stringОкруглить десятичную строку до целого в сторону −∞.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Число в десятичной строковой записи; scale не передаётся. |
| Возврат | Строка целого числа без дробной части. |
| Отказы | Плохая строка → ValueError; несовместимый тип → TypeError. |
| Версия | PHP 8.4+ |
- Вход 2.1
- bcfloor выбирает целое в сторону −∞
- Возврат 2
<?php
echo bcfloor('2.1'), "\n";
echo bcfloor('-2.1'), "\n";
Ожидаемый результат
2
-3
Направление выбирается на числовой прямой. «Вверх» не означает увеличить модуль отрицательного числа.
<?php
function lowerBucket($measurement) { return bcfloor($measurement); }
echo lowerBucket('3.8'), "\n";
echo lowerBucket('-0.2'), "\n";
Ожидаемый результат
3
-1
Величины принадлежат интервалам [3,4) и [−1,0). Усечение к нулю ошибочно поместило бы −0.2 в другой интервал.
Практическая граница. Не зависит от bcscale. Для двух знаков после точки используйте bcround с соответствующим RoundingMode. Не переводите результат в int без проверки диапазона.
Соседние инструменты: bcceil, bcround, BcMath\Number::floor. Выбор по задаче.
bcroundОкруглить точное десятичное значение по явно выбранному правилу.
bcround(string $num, int $precision = 0, RoundingMode $mode = RoundingMode::HalfAwayFromZero): stringОкруглить точное десятичное значение по явно выбранному правилу.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. RoundingMode::HalfEven — именованный вариант правила округления, а не строка или вызов. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Десятичная строка. |
| precision | 0 — единицы, 2 — сотые, −1 — десятки, −2 — сотни. Это число десятичных мест, не общее количество значащих цифр. |
| mode | Один из восьми вариантов RoundingMode. По умолчанию ближайшее, при половине — от нуля. Старые PHP_ROUND_* int-константы здесь не принимаются. |
| Возврат | Строка с округлённым числом; при положительной precision дополняется нулями. |
| Отказы | Плохая строка → ValueError. В реализации 8.5.11 положительная precision ограничена 2147483647 (превышение → ValueError), отрицательная помещается в int PHP. Manual также указывает неверный mode → ValueError, но публичная типизированная сигнатура при int/чужом enum даёт TypeError; корректные варианты RoundingMode замкнуты. |
| Версия | PHP 8.4+ |
- 12.345
- precision 2 и HalfAwayFromZero
- 12.35
<?php
echo bcround('12.345', 2), "\n";
echo bcround('126', -1), "\n";
echo bcround('2.5', 3), "\n";
Ожидаемый результат
12.35
130
2.500
Знак precision указывает сторону от десятичной точки. В отличие от scale округление учитывает удаляемую часть.
<?php
echo bcround('2.345', 2, RoundingMode::HalfEven), "\n";
echo bcround('-2.345', 2, RoundingMode::HalfAwayFromZero), "\n";
try { bcround('1.5', 0, PHP_ROUND_HALF_UP); }
catch (TypeError $error) { echo "Нужен вариант RoundingMode\n"; }
Ожидаемый результат
2.34
-2.35
Нужен вариант RoundingMode
HalfEven выбирает чётную последнюю сохраняемую цифру при точной половине. Режим обязан совпадать с договором расчёта; один режим не универсально «правильнее» другого.
<?php
try { bcround('12,30', 2); }
catch (ValueError $error) { echo "Неверная запись числа\n"; }
try { bcadd('1', '2', -1); }
catch (ValueError $error) { echo "Отрицательный scale запрещён\n"; }
echo bcround('126', -1), "\n";
Ожидаемый результат
Неверная запись числа
Отрицательный scale запрещён
130
Отрицательная precision у округления полезна и разрешена, отрицательный scale у арифметики — ошибка. Это два разных параметра.
Практическая граница. PHP 8.4+. На 8.2/8.3 встроенного bcround нет: не превращайте строку во float ради round; применяйте проверенную decimal/money-библиотеку с нужной политикой. Очень большая precision требует памяти; ограничьте её диапазоном задачи.
Соседние инструменты: RoundingMode, bcceil, bcfloor, BcMath\Number::round. Выбор по задаче.
BcMath\NumberХранить точное десятичное значение вместе с его масштабом и получать новые числа при вычислениях.
final readonly class BcMath\Number implements StringableХранить точное десятичное значение вместе с его масштабом и получать новые числа при вычислениях.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| value | Публичное readonly string-свойство: десятичное значение. |
| scale | Публичное readonly int-свойство: количество знаков после точки. |
| final / readonly | Наследование и изменение свойств запрещены. Это встроенный неизменяемый объект значения, а не запись баланса в БД. |
| Stringable | Поддерживает строковое представление; арифметические/сравнительные операторы перегружены именно этим встроенным классом. |
| Возврат | Методы вычислений создают новый Number. Результат может отличаться по scale; bcscale()/INI не участвуют. |
| Отказы | Изменение readonly свойства → Error; ошибки конкретных входов описаны у методов. |
| Версия | PHP 8.4+ |
- price: Number 12.30, scale 2
- price->mul(3) создаёт другой Number
- total 36.90; price остаётся 12.30
<?php
$price = new BcMath\Number('12.30');
$total = $price->mul(3);
echo $price->value, " / ", $price->scale, "\n";
echo $total->value, " / ", $total->scale, "\n";
Ожидаемый результат
12.30 / 2
36.90 / 2
Объект берёт на себя десятичное представление, но не хранит валюту, ставку налога или смысл «за штуку». Эти сведения остаются частью модели приложения.
<?php
$price = new BcMath\Number('5.25');
$before = $price;
$total = $price * 2 + '0.50';
$price += '1.00';
echo $total, "\n", $before, "\n", $price, "\n";
Ожидаемый результат
11.00
5.25
6.25
+ − * / % ** соответствуют методам с scale null. += присваивает переменной новый объект; прежнее число не меняется. Это специальная возможность Number, а не правило для любого пользовательского класса.
<?php
$a = new BcMath\Number('2.00');
$b = new BcMath\Number('2');
var_dump($a == $b, $a === $b, $a->compare($b) === 0);
var_dump((bool) new BcMath\Number('0.00'));
try { $a->value = '3'; }
catch (Error $error) { echo "Значение нельзя переписать\n"; }
Ожидаемый результат
bool(true)
bool(false)
bool(true)
bool(false)
Значение нельзя переписать
== сравнивает числа; === для объектов требует тот же экземпляр. Преобразование Number нуля в bool даёт false — это специальная реализация класса, не общая ложность объектов.
Практическая граница. Поиск нуля через if($number) отличается от проверки строки "0.00". В арифметике с обычными десятичными строками без объекта PHP может выбрать float: нужен Number хотя бы с одной стороны. Для явной точности удобнее методы, а для обычного PHP 8.2/8.3 — bc-функции.
Соседние инструменты: BcMath\Number::__construct, BcMath\Number::compare, bcadd, bcscale. Выбор по задаче.
BcMath\Number::__constructСоздать проверенное десятичное число из строки или целого.
new BcMath\Number(string|int $num)Создать проверенное десятичное число из строки или целого.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. declare(strict_types=1) включает строгую передачу скалярных аргументов в этом файле. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | int даёт scale 0; строка разбирается, scale равен количеству её дробных разрядов, включая хвостовые нули. Number не входит в контракт самого конструктора. |
| Возврат | new возвращает созданный Number; сам конструктор не имеет возвращаемого типа. |
| Отказы | Неправильная строка → ValueError; float при strict_types=1 → TypeError. |
| Версия | PHP 8.4+ |
- Строка +0012.300
- Убираем лишний плюс и ведущие нули
- value 12.300 и scale 3
<?php
$amount = new BcMath\Number('+0012.300');
$count = new BcMath\Number(12);
echo $amount->value, ':', $amount->scale, "\n";
echo $count->value, ':', $count->scale, "\n";
Ожидаемый результат
12.300:3
12:0
Исходный текст нормализуется. scale 3 не доказывает измерительную точность или валюту; это число хранимых знаков.
<?php
declare(strict_types=1);
try { new BcMath\Number('12,30'); }
catch (ValueError $error) { echo "Нужна десятичная точка\n"; }
try { new BcMath\Number(12.3); }
catch (TypeError $error) { echo "Передайте исходную строку\n"; }
Ожидаемый результат
Нужна десятичная точка
Передайте исходную строку
Нестрогие скалярные преобразования не делают float точным. Для копирования Number обычно достаточно присвоить тот же неизменяемый объект; при необходимости можно создать новый из value.
Практическая граница. Конструктор подтверждает синтаксис BCMath, но не правила цены. Пустая строка и один знак в текущем PHP превращаются в ноль, поэтому обязательность и формат внешнего поля нужно проверять до new.
Соседние инструменты: BcMath\Number, BcMath\Number::__serialize. Выбор по задаче.
BcMath\Number::addСложить сумму заказа с доставкой.
Number::add(Number|string|int $num, ?int $scale = null): NumberСложить сумму заказа с доставкой.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. |
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. |
| Автоматический scale | Максимум масштабов двух входов. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. |
| Отказы | Плохая строка или недопустимый scale → ValueError; несовместимый тип → TypeError. |
| Версия | PHP 8.4+ |
- Сумма 12.30
- Добавляем 0.125
- Новый результат 12.425, scale 3
<?php
$amount = new BcMath\Number('12.30');
$result = $amount->add('0.125');
echo $result, ':', $result->scale, "\n";
echo $amount, "\n";
Ожидаемый результат
12.425:3
12.30
Значение value — десятичная строка, а scale — число знаков после точки. Каждый вход сохраняет собственный масштаб.
<?php
function withShipping($subtotal, $shipping) {
return $subtotal->add($shipping, 2);
}
echo withShipping(new BcMath\Number('24.50'), '3.70'), "\n";
echo (new BcMath\Number('1.999'))->add('0', 2), "\n";
Ожидаемый результат
28.20
1.99
Последующие вычисления работают с новым результатом. Явный scale ограничивает разряды, а отказ нулевого делителя, если он используется, обрабатывается отдельно.
Практическая граница. Не путайте уменьшение scale с округлением. Новый результат нужно сохранить; вызов $amount->add(...) сам по себе не меняет $amount.
Соседние инструменты: bcadd, BcMath\Number::sub, BcMath\Number::round. Выбор по задаче.
BcMath\Number::subВычесть возврат, сохранив исходную сумму для журнала.
Number::sub(Number|string|int $num, ?int $scale = null): NumberВычесть возврат, сохранив исходную сумму для журнала.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. |
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. |
| Автоматический scale | Максимум масштабов двух входов. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. |
| Отказы | Плохая строка или недопустимый scale → ValueError; несовместимый тип → TypeError. |
| Версия | PHP 8.4+ |
- Сумма 20.00
- Возврат 3.125
- Новый остаток 16.875
<?php
$amount = new BcMath\Number('20.00');
echo $amount->sub('3.125'), "\n";
echo $amount, "\n";
Ожидаемый результат
16.875
20.00
Значение value — десятичная строка, а scale — число знаков после точки. Каждый вход сохраняет собственный масштаб.
<?php
function remaining($amount, $refund) {
return $amount->sub($refund, 2);
}
echo remaining(new BcMath\Number('15.50'), 4), "\n";
echo remaining(new BcMath\Number('1.00'), '2.00'), "\n";
Ожидаемый результат
11.50
-1.00
Последующие вычисления работают с новым результатом. Явный scale ограничивает разряды, а отказ нулевого делителя, если он используется, обрабатывается отдельно.
Практическая граница. Отрицательный ответ допустим API; запрет переплаты/перевозврата — отдельный инвариант приложения. Неизменяемый объект не заменяет транзакцию БД.
Соседние инструменты: bcsub, BcMath\Number::add, BcMath\Number::round. Выбор по задаче.
BcMath\Number::mulУмножить тариф на количество или коэффициент.
Number::mul(Number|string|int $num, ?int $scale = null): NumberУмножить тариф на количество или коэффициент.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. |
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. |
| Автоматический scale | Сумма масштабов двух входов; выход за допустимый масштаб → ValueError. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. |
| Отказы | Плохая строка или недопустимый scale → ValueError; несовместимый тип → TypeError. Автоматический scale также должен оставаться в диапазоне. |
| Версия | PHP 8.4+ |
- Тариф 2.50, scale 2
- Коэффициент 1.2, scale 1
- Результат 3.000, scale 3
<?php
$tariff = new BcMath\Number('2.50');
$result = $tariff->mul('1.2');
echo $result, ':', $result->scale, "\n";
Ожидаемый результат
3.000:3
Значение value — десятичная строка, а scale — число знаков после точки. Каждый вход сохраняет собственный масштаб.
<?php
function lineTotal($price, $quantity) { return $price->mul($quantity, 2); }
echo lineTotal(new BcMath\Number('7.35'), 3), "\n";
echo (new BcMath\Number('19.99'))->mul('0.075')->round(2), "\n";
Ожидаемый результат
22.05
1.50
Последующие вычисления работают с новым результатом. Явный scale ограничивает разряды, а отказ нулевого делителя, если он используется, обрабатывается отдельно.
Практическая граница. Автоматический scale сохраняет все разряды конечного произведения, но растёт при длинной цепочке умножений. Округляйте на согласованных границах и ограничивайте число/размер входов.
Соседние инструменты: bcmul, BcMath\Number::div, BcMath\Number::round. Выбор по задаче.
BcMath\Number::modНайти остаток длины после целого количества отрезков.
Number::mod(Number|string|int $num, ?int $scale = null): NumberНайти остаток длины после целого количества отрезков.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. |
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. |
| Автоматический scale | Максимум масштабов двух входов. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. |
| Отказы | Плохая строка или недопустимый scale → ValueError; несовместимый тип → TypeError. Делитель 0 → DivisionByZeroError. |
| Версия | PHP 8.4+ |
- Длина 17.55
- Отрезки по 4.2
- Остаток 0.75, scale 2
<?php
$length = new BcMath\Number('17.55');
$rest = $length->mod('4.2');
echo $rest, ':', $rest->scale, "\n";
echo $length->mod('4.2', 1), "\n";
Ожидаемый результат
0.75:2
0.7
Значение value — десятичная строка, а scale — число знаков после точки. Каждый вход сохраняет собственный масштаб.
<?php
echo (new BcMath\Number('-17.55'))->mod('4.2'), "\n";
try { (new BcMath\Number('8'))->mod(0); }
catch (DivisionByZeroError $error) { echo "Нулевой размер отрезка\n"; }
Ожидаемый результат
-0.75
Нулевой размер отрезка
Последующие вычисления работают с новым результатом. Явный scale ограничивает разряды, а отказ нулевого делителя, если он используется, обрабатывается отдельно.
Практическая граница. Ненулевой остаток имеет знак исходного числа, а не делителя. Перегруженный % для Number сохраняет десятичное поведение, в отличие от обычного % с простыми числовыми строками.
Соседние инструменты: bcmod, BcMath\Number::divmod, BcMath\Number::round. Выбор по задаче.
BcMath\Number::divРазделить число и сохранить достаточные дополнительные разряды в пределах автоматического правила.
Number::div(Number|string|int $num, ?int $scale = null): NumberРазделить число и сохранить достаточные дополнительные разряды в пределах автоматического правила.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. Делитель не должен быть нулём. |
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. |
| Автоматическое правило | От scale делимого до scale делимого + 10. Расширение только по необходимости; хвостовые нули расширенной части удаляются, но не ниже исходного scale. Масштаб делителя не задаёт нижнюю границу. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. |
| Отказы | Нулевой делитель → DivisionByZeroError. Плохая строка, заданный/вычисленный scale вне диапазона → ValueError; несовместимый тип → TypeError. |
| Версия | PHP 8.4+ |
- 1.00, исходный scale 2
- Деление на 3
- 0.333333333333, scale 12
<?php
$one = new BcMath\Number('1.00');
$third = $one->div(3);
$eighth = $one->div(8);
echo $third, ':', $third->scale, "\n";
echo $eighth, ':', $eighth->scale, "\n";
Ожидаемый результат
0.333333333333:12
0.125:3
Периодическая дробь дошла до предела +10. Для восьмой части понадобился только один дополнительный разряд.
<?php
$one = new BcMath\Number('1');
echo $one->div('2000000000000'), "\n";
echo $one->div('2000000000000', 13), "\n";
echo (new BcMath\Number('10.00'))->div(3, 2), "\n";
Ожидаемый результат
0
0.0000000000005
3.33
Автоматика не бесконечна: ненулевое частное может стать нулём. Последний расчёт показывает явное усечение до сотых, а не округление.
Практическая граница. Автоматический +10 — договор API, не универсальная гарантия требуемой погрешности. Для денег/измерений выбирайте масштаб по задаче, а для распределения всей суммы используйте divmod.
Соседние инструменты: bcdiv, BcMath\Number::divmod, BcMath\Number::sqrt. Выбор по задаче.
BcMath\Number::divmodРазделить количество на полные группы и получить остаток объектами Number.
Number::divmod(Number|string|int $num, ?int $scale = null): arrayРазделить количество на полные группы и получить остаток объектами Number.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. [...] создаёт массив; [$a, $b] = ... раскладывает два результата по переменным, $data["value"] читает элемент по ключу. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. Ненулевой делитель. |
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. Относится к остатку. |
| Автоматическое правило | Частное всегда scale 0. Остаток получает максимум масштабов входов. |
| Возврат | Массив [новый Number частного, новый Number остатка]; частное усечено к нулю. |
| Отказы | ValueError для плохой строки/scale, DivisionByZeroError для нуля, TypeError для несовместимого типа. |
| Версия | PHP 8.4+ |
- 17.55 / 4.2
- Целое частное 4 (scale 0)
- Остаток 0.75 (scale 2)
<?php
[$q, $r] = (new BcMath\Number('17.55'))->divmod('4.2');
echo $q, ':', $q->scale, "\n";
echo $r, ':', $r->scale, "\n";
Ожидаемый результат
4:0
0.75:2
Два объекта независимы от исходного; каждое имеет собственный масштаб.
<?php
function packing($items, $size) {
[$boxes, $loose] = $items->divmod($size);
return 'Коробки: ' . $boxes . '; отдельно: ' . $loose;
}
echo packing(new BcMath\Number('53'), 12), "\n";
[$q, $r] = (new BcMath\Number('-17.55'))->divmod('4.2', 1);
echo $q, ' / ', $r, "\n";
Ожидаемый результат
Коробки: 4; отдельно: 5
-4 / -0.7
Точка соединяет текст и строковое представление Number. Во второй строке недостаточный scale остатка разрушает точное восстановление исходного делимого.
Практическая граница. Это не пара «полное десятичное частное и остаток»: частное целое. Проверьте положительность размера коробки; нулевой размер API отклоняет сам.
Соседние инструменты: bcdivmod, BcMath\Number::div, BcMath\Number::mod. Выбор по задаче.
BcMath\Number::compareПроверить числовое равенство или порядок, не привязываясь к идентичности объектов.
Number::compare(Number|string|int $num, ?int $scale = null): intПроверить числовое равенство или порядок, не привязываясь к идентичности объектов.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| num | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. |
| scale | null: все разряды обоих чисел; целое 0…2147483647: игнорировать остальные дробные разряды. Не использует bcscale. |
| Возврат | int −1 / 0 / 1: это число меньше / равно / больше num. |
| Отказы | Плохая строка/scale → ValueError; несовместимый тип → TypeError. |
| Версия | PHP 8.4+ |
- 2.005 сравниваем с 2.009
- Весь масштаб
- Левое меньше: int −1
<?php
$a = new BcMath\Number('2.005');
var_dump($a->compare('2.009'));
var_dump($a->compare('2.009', 2));
var_dump($a->compare('2.0050') === 0);
Ожидаемый результат
int(-1)
int(0)
bool(true)
null отличается от процедурного bccomp(null), который берёт глобальный scale. Строгое сравнение с int 0 проверяет равенство результата сравнения.
<?php
function fitsBudget($cost, $limit) {
return $cost->compare($limit) <= 0;
}
var_dump(fitsBudget(new BcMath\Number('100.0001'), '100'));
var_dump(fitsBudget(new BcMath\Number('100.0000'), '100'));
Ожидаемый результат
bool(false)
bool(true)
В этой задаче даже одна десятитысячная значима. Сравнение со scale 2 ошибочно пропустило бы превышение.
Практическая граница. compare() возвращает int, а не bool. === между двумя Number сравнивает идентичность, не арифметическое равенство; == и <=> встроенный класс перегружает для чисел.
Соседние инструменты: bccomp, BcMath\Number. Выбор по задаче.
BcMath\Number::powВозвести число в целую степень с автоматическим масштабом результата.
Number::pow(Number|string|int $exponent, ?int $scale = null): NumberВозвести число в целую степень с автоматическим масштабом результата.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| exponent | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. Значение без ненулевой дробной части. Диапазон платформенный, не уже −2147483648…2147483647. |
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. |
| Автоматическое правило | Положительный exponent: scale основания × exponent; нулевой: 0; отрицательный: от scale основания до +10, как div(). |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. |
| Отказы | Плохой/дробный/непомещающийся показатель или заданный/расчётный scale вне диапазона → ValueError. Ноль в отрицательной степени → DivisionByZeroError. |
| Версия | PHP 8.4+ |
- 1.20, scale 2
- pow(3): три множителя
- 1.728000, scale 6
<?php
$base = new BcMath\Number('1.20');
echo $base->pow(3), "\n";
echo $base->pow(0), "\n";
echo (new BcMath\Number('2.0'))->pow(-3), "\n";
Ожидаемый результат
1.728000
1
0.125
Для положительной степени сохраняется сумма дробных разрядов множителей. Для отрицательной возможна ограниченная периодическая дробь.
<?php
$factor = new BcMath\Number('1.02');
echo $factor->pow(3)->mul('1000')->round(2), "\n";
try { $factor->pow('0.5'); }
catch (ValueError $error) { echo "Дробная степень не поддерживается\n"; }
Ожидаемый результат
1061.21
Дробная степень не поддерживается
Цепочка вызывает следующий метод у результата предыдущего. Квадратный корень вычисляется sqrt, а не pow(0.5).
Практическая граница. Проверяйте разумный предел exponent и длину входов. Формально допустимая степень может потребовать больше ресурсов, чем доступно веб-запросу.
Соседние инструменты: bcpow, BcMath\Number::powmod, BcMath\Number::sqrt. Выбор по задаче.
BcMath\Number::powmodВычислить модульную степень, не материализуя полную огромную степень.
Number::powmod(Number|string|int $exponent, Number|string|int $modulus, ?int $scale = null): NumberВычислить модульную степень, не материализуя полную огромную степень.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| exponent | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. Неотрицательное целое значение. |
| modulus | Другой Number, десятичная строка или int; float не входит в заявленный контракт. В строгом режиме он вызывает TypeError. Ненулевое целое значение. |
| Основание | Текущий Number тоже должен иметь целочисленное значение. |
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. При null результат всегда scale 0. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. |
| Отказы | Ненулевая дробная часть любого операнда/плохая строка/отрицательный показатель/недопустимый scale → ValueError; modulus 0 → DivisionByZeroError. |
| Версия | PHP 8.4+ |
- 7 в степени 4
- Сокращение по модулю 13
- Новый Number 9, scale 0
<?php
$base = new BcMath\Number('7');
echo $base->powmod(4, 13), "\n";
echo $base->powmod(4, 13, 2), "\n";
Ожидаемый результат
9
9.00
Математический результат целый, но явный scale позволяет формат с нулями.
<?php
echo (new BcMath\Number('2'))->powmod(1000, 97), "\n";
try { (new BcMath\Number('2.5'))->powmod(3, 7); }
catch (ValueError $error) { echo "Нужно целое основание\n"; }
Ожидаемый результат
36
Нужно целое основание
Проверка относится и к самому объекту, не только к аргументам метода.
Практическая граница. Ненулевые отрицательные остатки возможны. Алгоритм не является обещанием постоянного времени исполнения и не заменяет криптографический протокол.
Соседние инструменты: bcpowmod, BcMath\Number::pow, BcMath\Number::mod. Выбор по задаче.
BcMath\Number::sqrtПолучить неотрицательный квадратный корень и управлять числом его разрядов.
Number::sqrt(?int $scale = null): NumberПолучить неотрицательный квадратный корень и управлять числом его разрядов.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| scale | Явный scale: 0…2147483647; null/пропуск выбирает правило этого метода. bcscale() и bcmath.scale на объект не влияют. Уменьшение scale усекает к нулю, не округляет. |
| Автоматическое правило | Исходный scale, расширенный по необходимости максимум на 10; хвостовые нули расширения удаляются, ниже исходного scale не опускается. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. |
| Отказы | Отрицательное число либо заданный/вычисленный scale вне диапазона → ValueError. |
| Версия | PHP 8.4+ |
- Площадь 6.25, scale 2
- sqrt()
- Сторона 2.50, scale 2
<?php
echo (new BcMath\Number('6.25'))->sqrt(), "\n";
echo (new BcMath\Number('3'))->sqrt(5), "\n";
Ожидаемый результат
2.50
1.73205
Явный scale для иррационального корня означает усечение, а не точное представление всей бесконечной дроби.
<?php
function sideFromArea($area) { return $area->sqrt(3); }
echo sideFromArea(new BcMath\Number('12.25')), "\n";
try { sideFromArea(new BcMath\Number('-1')); }
catch (ValueError $error) { echo "Нет действительной стороны\n"; }
Ожидаемый результат
3.500
Нет действительной стороны
Обработчик ошибки преобразует технический отказ в смысл задачи. Внешняя форма должна объяснять причину ещё до расчёта.
Практическая граница. Количество десятичных разрядов результата не равно доказанной точности исходных измерений. Для очень маленького корня автоматического масштаба может не хватить.
Соседние инструменты: bcsqrt, BcMath\Number::pow, BcMath\Number::div. Выбор по задаче.
BcMath\Number::ceilПолучить ближайшее целое не меньше исходного.
Number::ceil(): NumberПолучить ближайшее целое не меньше исходного.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| Параметры | Нет. Метод работает со значением текущего объекта. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. У результата scale всегда 0. |
| Отказы | Для корректного созданного Number отдельного доменного отказа нет; недопустимая строка отклоняется ещё конструктором. |
| Версия | PHP 8.4+ |
- Исходное 2.1
- ceil выбирает целое не меньше исходного
- Новый Number 3, scale 0
<?php
$positive = (new BcMath\Number('2.1'))->ceil();
$negative = (new BcMath\Number('-2.1'))->ceil();
echo $positive, ':', $positive->scale, "\n";
echo $negative, ':', $negative->scale, "\n";
Ожидаемый результат
3:0
-2:0
Направление сравнивается на числовой прямой. Операция не меняет исходное число.
<?php
$items = new BcMath\Number('17');
$needed = $items->div(4)->ceil();
echo $needed, "\n";
echo $items, "\n";
Ожидаемый результат
5
17
Для 17/4 автоматическое деление даёт точное 4.25. Для больших целых и опасности потери малой дроби выбирайте divmod: ceil не восстановит уже потерянный остаток.
Практическая граница. Это округление до целого независимо от bcscale. Для разрядов после точки есть round с нужным RoundingMode; для точных денежных единиц не приводите произвольно большой результат к int.
Соседние инструменты: bcceil, BcMath\Number::floor, BcMath\Number::round. Выбор по задаче.
BcMath\Number::floorПолучить ближайшее целое не больше исходного.
Number::floor(): NumberПолучить ближайшее целое не больше исходного.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. function name($x) { ... } объявляет повторяемое действие; параметр получает вход, return отдаёт результат вызывающему коду. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| Параметры | Нет. Метод работает со значением текущего объекта. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. У результата scale всегда 0. |
| Отказы | Для корректного созданного Number отдельного доменного отказа нет; недопустимая строка отклоняется ещё конструктором. |
| Версия | PHP 8.4+ |
- Исходное 2.1
- floor выбирает целое не больше исходного
- Новый Number 2, scale 0
<?php
$positive = (new BcMath\Number('2.1'))->floor();
$negative = (new BcMath\Number('-2.1'))->floor();
echo $positive, ':', $positive->scale, "\n";
echo $negative, ':', $negative->scale, "\n";
Ожидаемый результат
2:0
-3:0
Направление сравнивается на числовой прямой. Операция не меняет исходное число.
<?php
function cellStart($measurement) { return $measurement->floor(); }
echo cellStart(new BcMath\Number('4.9')), "\n";
echo cellStart(new BcMath\Number('-0.1')), "\n";
Ожидаемый результат
4
-1
Нижняя граница отрицательного измерения — −1, а не 0. Это полезно при разбиении числовой шкалы на интервалы.
Практическая граница. Это округление до целого независимо от bcscale. Для разрядов после точки есть round с нужным RoundingMode; для точных денежных единиц не приводите произвольно большой результат к int.
Соседние инструменты: bcfloor, BcMath\Number::ceil, BcMath\Number::round. Выбор по задаче.
BcMath\Number::roundПолучить новое число, округлённое до выбранного десятичного разряда.
Number::round(int $precision = 0, RoundingMode $mode = RoundingMode::HalfAwayFromZero): NumberПолучить новое число, округлённое до выбранного десятичного разряда.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. RoundingMode::HalfEven — именованный вариант правила округления, а не строка или вызов. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| precision | Положительная: знаки после точки. 0: единицы. Отрицательная: десятки, сотни и т. д. Это не число значащих цифр. |
| mode | Один из восьми RoundingMode; по умолчанию ближайшее с точной половиной от нуля. |
| Возврат | Возвращается новый Number; исходный объект сохраняет value и scale. Результат нужно присвоить или передать дальше. scale результата равен положительной precision, а при precision ≤ 0 равен 0. |
| Отказы | Manual указывает ValueError для неверного mode; передача int вместо enum в проверенном API даёт TypeError. В PHP 8.5.11 precision > 2147483647 отклоняется с ValueError; отрицательная precision помещается в int PHP. Допустимый диапазон не гарантирует доступной памяти. |
| Версия | PHP 8.4+ |
- Исходная цена 2.345
- round(2, HalfEven)
- Новая цена 2.34, исходная 2.345
<?php
$raw = new BcMath\Number('2.345');
echo $raw->round(2, RoundingMode::HalfEven), "\n";
echo $raw->round(2, RoundingMode::HalfAwayFromZero), "\n";
echo $raw, "\n";
Ожидаемый результат
2.34
2.35
2.345
Результаты разных политик законно различаются. Копия raw остаётся для аудита вычисления.
<?php
$price = new BcMath\Number('126.4');
$tens = $price->round(-1);
$padded = $price->round(3);
echo $tens, ':', $tens->scale, "\n";
echo $padded, ':', $padded->scale, "\n";
Ожидаемый результат
130:0
126.400:3
Округление до десятков не создаёт отрицательный scale. Дополнение нулями меняет представление, но не числовое значение.
Практическая граница. Сначала согласуйте, округляется ли строка заказа, ставка, комиссия или итог целиком. Number не выбирает этап округления. Полная таблица восьми режимов есть в начале этой главы.
Соседние инструменты: bcround, RoundingMode, BcMath\Number::ceil, BcMath\Number::floor. Выбор по задаче.
BcMath\Number::__toStringПолучить исходную десятичную строку для текста или явной передачи в другой интерфейс.
Number::__toString(): stringПолучить исходную десятичную строку для текста или явной передачи в другой интерфейс.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. [...] создаёт массив; [$a, $b] = ... раскладывает два результата по переменным, $data["value"] читает элемент по ключу. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| Параметры | Нет; обычно вызывается автоматически при echo или (string). |
| Возврат | Строка свойства value, включая значимые для представления хвостовые нули. |
| Отказы | Метод не форматирует локаль и не преобразует валюту. |
| Версия | PHP 8.4+ |
- Number 12.300
- Явное (string)
- Строка 12.300 без преобразования в float
<?php
$amount = new BcMath\Number('12.300');
$text = (string) $amount;
echo $text, "\n";
var_dump($text === $amount->value);
Ожидаемый результат
12.300
bool(true)
Круглые скобки с string — явное приведение к строке. Оно вызывает __toString; прямой вызов метода тоже допустим, но обычно не нужен.
<?php
$amount = new BcMath\Number('9007199254740993.20');
$payload = ['amount' => (string) $amount, 'currency' => 'RUB'];
echo json_encode($payload, JSON_THROW_ON_ERROR), "\n";
Ожидаемый результат
{"amount":"9007199254740993.20","currency":"RUB"}
Ключи подписывают поля массива, json_encode создаёт JSON. Строка согласована с контрактом API: не используйте JSON_NUMERIC_CHECK, который превратит её в потенциально неточное число. JSON_THROW_ON_ERROR сообщает об ошибке кодирования.
Практическая граница. Stringable не означает, что Number будет принят строковым параметром при strict_types=1: передавайте явное (string). Приведение самого объекта к int/float не является API точного значения; форматирующие функции с float могут уничтожить разряды.
Соседние инструменты: BcMath\Number::__construct, BcMath\Number::__serialize. Выбор по задаче.
BcMath\Number::__serializeПодготовить внутренние данные Number для штатного PHP serialize().
Number::__serialize(): arrayПодготовить внутренние данные Number для штатного PHP serialize().
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. [...] создаёт массив; [$a, $b] = ... раскладывает два результата по переменным, $data["value"] читает элемент по ключу. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| Параметры | Нет. serialize($number) вызывает этот hook автоматически. |
| Возврат | Массив состояния; в PHP 8.5.11 это ["value" => десятичная строка]. Scale восстанавливается из её разрядов. |
| Отказы | Для штатного созданного Number отдельного доменного отказа нет. |
| Версия | PHP 8.4+ |
Магические методы и жизненный цикл объясняет вызов hook движком; здесь показан конкретный путь числового состояния.
- Number 12.300
- serialize вызывает __serialize
- Состояние хранит value 12.300, откуда восстановится scale 3
<?php
$number = new BcMath\Number('12.300');
$state = $number->__serialize();
echo $state['value'], "\n";
echo count($state), "\n";
Ожидаемый результат
12.300
1
Прямой вызов нужен здесь для объяснения механизма. Его массив ещё не является строкой PHP-сериализации.
<?php
$original = new BcMath\Number('12345678901234567890.00');
$snapshot = serialize($original);
$copy = unserialize($snapshot, ['allowed_classes' => [BcMath\Number::class]]);
echo $copy, ':', $copy->scale, "\n";
var_dump($copy->compare($original) === 0, $copy === $original);
Ожидаемый результат
12345678901234567890.00:2
bool(true)
bool(false)
::class даёт имя класса; список allowed_classes ограничивает восстановление этой локальной копии. Возникает новый объект с тем же числом, а не ссылка на старый.
Практическая граница. Не принимайте сериализованные PHP-объекты из недоверенного запроса. allowed_classes не превращает недоверенный формат в безопасный протокол. Для обмена обычно яснее JSON с десятичной строкой и валидацией. Структура hook показана для проверенной версии, не как долгосрочная внешняя схема.
Соседние инструменты: BcMath\Number::__unserialize, BcMath\Number::__toString. Выбор по задаче.
BcMath\Number::__unserializeВосстановить новый Number из состояния, созданного сериализацией.
Number::__unserialize(array $data): voidВосстановить новый Number из состояния, созданного сериализацией.
$name — переменная; = сохраняет результат, кавычки задают строку, ; завершает команду. name(...) вызывает функцию с аргументами через запятую. echo выводит, "\n" переносит строку; var_dump показывает значение и его тип. new BcMath\Number(...) создаёт число-объект. Обратная косая черта — часть полного имени класса. $number->method(...) вызывает действие этого объекта; ->value и ->scale читают его свойства. public означает доступность извне, readonly — запрет изменения после инициализации, final — запрет наследования. try начинает попытку, catch (Тип $error) обрабатывает пойманный отказ, finally выполняет завершающие действия. throw new ... сообщает об отказе; finally его не подавляет. [...] создаёт массив; [$a, $b] = ... раскладывает два результата по переменным, $data["value"] читает элемент по ключу. Объект и обращение к нему. Начало: переменная; Вызов и return.
| Часть договора | Значение |
|---|---|
| data | Ассоциативный массив состояния. В PHP 8.5.11 требуется непустая строка value в корректной BCMath-записи; scale выводится из неё. |
| Обычный вызов | unserialize() выделяет экземпляр и вызывает hook. Это не setter уже созданного Number. |
| Возврат | void: значимого возвращаемого результата нет; инициализируется восстанавливаемый экземпляр. |
| Отказы | На официальной странице заявлен ValueError. Однако PHP 8.5.11 и его исходник выбрасывают обычный Exception для неверного массива/числа. Повторная инициализация корректным состоянием → Error readonly. Несовместимый тип data → TypeError. |
| Версия | PHP 8.4+ |
Расхождение подтверждено первичным исходником php-8.5.11/ext/bcmath/bcmath.c, метод __unserialize и отдельным выполнением. В другой версии тип отказа нужно сверять повторно.
- Локальный serialize содержит 7.250
- unserialize создаёт новый экземпляр
- __unserialize восстанавливает value и scale 3
<?php
$snapshot = serialize(new BcMath\Number('7.250'));
$restored = unserialize($snapshot, ['allowed_classes' => [BcMath\Number::class]]);
echo $restored->value, ':', $restored->scale, "\n";
Ожидаемый результат
7.250:3
Конструктор вручную не вызывается; механизм восстановления инициализирует новый объект. Здесь строка создана самим примером, внешних данных нет.
<?php
$number = new BcMath\Number('7.25');
try { $number->__unserialize(['value' => 5]); }
catch (Throwable $error) { echo $error::class, "\n"; }
try { $number->__unserialize(['value' => '9.00']); }
catch (Throwable $error) { echo $error::class, "\n"; }
echo $number, "\n";
Ожидаемый результат
Exception
Error
7.25
Это диагностический опыт PHP 8.5.11, не рекомендуемый путь загрузки данных. Throwable охватывает обе ветви отказа; ::class показывает фактический класс ошибки. Исходное значение не изменилось.
Практическая граница. Не обходите readonly повторным hook. Не стройте код на предположении, что реальная ошибка обязательно ValueError: оно расходится с исследованной реализацией. Внешнюю цену принимайте строкой, проверяйте и создавайте через конструктор.
Соседние инструменты: BcMath\Number::__serialize, BcMath\Number::__construct. Выбор по задаче.
Источники и обсуждения
- PHP book.bc
- PHP bc.setup
- PHP bc.installation
- PHP bc.configuration
- PHP ref.bc
- PHP class.bcmath-number
- PHP function.bcadd
- PHP function.bcceil
- PHP function.bccomp
- PHP function.bcdiv
- PHP function.bcdivmod
- PHP function.bcfloor
- PHP function.bcmod
- PHP function.bcmul
- PHP function.bcpow
- PHP function.bcpowmod
- PHP function.bcround
- PHP function.bcscale
- PHP function.bcsqrt
- PHP function.bcsub
- PHP bcmath-number.add
- PHP bcmath-number.ceil
- PHP bcmath-number.compare
- PHP bcmath-number.construct
- PHP bcmath-number.div
- PHP bcmath-number.divmod
- PHP bcmath-number.floor
- PHP bcmath-number.mod
- PHP bcmath-number.mul
- PHP bcmath-number.pow
- PHP bcmath-number.powmod
- PHP bcmath-number.round
- PHP bcmath-number.serialize
- PHP bcmath-number.sqrt
- PHP bcmath-number.sub
- PHP bcmath-number.tostring
- PHP bcmath-number.unserialize
- PHP 8.5.11 BCMath implementation