Целочисленное деление в PHP: как получить частное без остатка

Раздел: Основы PHP -> Арифметические операции

Основы целочисленного деления в PHP

При работе с числами в PHP часто возникает необходимость разделить одно число на другое так, чтобы результатом была только целая часть, без учёта остатка. Такое деление называется целочисленным. В PHP для этого существует несколько подходов, каждый из которых имеет свои особенности.

Как выполнить деление нацело с помощью встроенного оператора?

Наиболее эффективным и читаемым способом является использование оператора intdiv. Он возвращает целое число (int), полученное в результате деления первого аргумента на второй, отбрасывая дробную часть в сторону нуля.

<?php
$result = intdiv(10, 3);
echo $result; // 3
?>

Php модуль числа (модуль числа в php (abs))

3

без остатка php (деление без остатка в php)

Оператор intdiv работает с целыми числами, но при передаче чисел с плавающей точкой они сначала преобразуются в целые. Важно помнить, что если делитель равен нулю, будет выброшено исключение DivisionByZeroError.

Типичная ошибка – деление на ноль. Решение – проверка делителя перед вызовом intdiv.

<?php
$a = 10;
$b = 0;
if ($b !== 0) {
    $result = intdiv($a, $b);
} else {
    echo 'Деление на ноль';
}
?>

Как получить целую часть деления с помощью приведения к int?

Можно использовать обычное деление / и затем привести результат к целому типу с помощью (int) или intval(). Этот способ возвращает целую часть, отбрасывая дробную часть в сторону нуля, подобно intdiv.

<?php
$a = 10;
$b = 3;
$result = (int)($a / $b);
echo $result; // 3
?>

Однако такой подход менее явный и может привести к путанице при чтении кода. Кроме того, если $a и $b – большие числа, результат деления может быть с плавающей точкой, что может вызвать потерю точности.

Проблема: при использовании float возможно неверное округление для очень больших чисел, выходящих за пределы точности double.

<?php
$a = 9999999999999999999;
$b = 1;
echo (int)($a / $b); // может вывести неверное значение из-за потери точности
?>

Решение – использовать intdiv, который работает с целыми числами как с bigint при необходимости (при сборке с поддержкой GMP).

Как выполнить деление без остатка с округлением вниз для положительных чисел?

Функция floor() округляет число вниз до ближайшего целого. Для положительных чисел результат деления и последующее применение floor даёт целую часть. Однако для отрицательных чисел поведение отличается – floor округляет в сторону минус бесконечности, тогда как intdiv отбрасывает дробную часть в сторону нуля.

<?php
$a = 10;
$b = 3;
$result = floor($a / $b);
echo $result; // 3
// Для отрицательных:
echo floor(-10 / 3); // -4, а intdiv(-10,3) даст -3
?>

Поэтому floor() подходит только для случаев, когда гарантированно работаем с положительными числами, и нужно именно округление вниз (в сторону меньшего).

Какие ещё существуют способы целочисленного деления?

Для работы с очень большими числами или строками можно использовать функцию bcdiv с параметром scale=0. Она выполняет деление с произвольной точностью и возвращает строку.

<?php
$a = '10000000000000000000';
$b = '3';
echo bcdiv($a, $b, 0); // 3333333333333333333
?>

Этот метод удобен для экономических расчётов, где важна точность больших чисел.

Расширенные примеры работы с целочисленным делением

Сравнение поведения intdiv и приведения типов на отрицательных числах

Пример
<?php
$a = -10;
$b = 3;
echo 'intdiv: ' . intdiv($a, $b) . PHP_EOL;      // -3
echo '(int) деления: ' . (int)($a / $b) . PHP_EOL; // -3
echo 'floor: ' . floor($a / $b) . PHP_EOL;       // -4
echo 'ceil: ' . ceil($a / $b) . PHP_EOL;        // -3
?>
intdiv: -3
(int) деления: -3
floor: -4
ceil: -3

Как видно, floor даёт результат, отличный от intdiv, поэтому для единообразного поведения по стандарту целочисленного деления (округление к нулю) следует использовать intdiv или (int).

Обработка деления на ноль с исключением

Пример
<?php
try {
    $result = intdiv(5, 0);
} catch (DivisionByZeroError $e) {
    echo 'Ошибка: ' . $e->getMessage();
}
?>
Ошибка: Division by zero

В отличие от обычного деления, где деление на ноль генерирует предупреждение и возвращает false или INF, intdiv генерирует исключение. Это делает код более безопасным.

Работа с числами с плавающей точкой

Пример
<?php
$a = 7.9;
$b = 2.1;
$resultIntDiv = intdiv($a, $b);   // сначала преобразует в int: 7 и 2 -> 3
$resultCast = (int)($a / $b);       // 7.9/2.1≈3.7619 -> 3
echo "intdiv: $resultIntDiv\n";
echo "(int): $resultCast";
?>
intdiv: 3
(int): 3

Обратите внимание: intdiv отбрасывает дробные части операндов перед делением, поэтому результат может отличаться от ожидаемого. Если нужно сначала выполнить деление с плавающей точкой, а затем отбросить дробную часть, лучше использовать (int)($a / $b).

Целочисленное деление с остатком (проверка кратности)

Пример
<?php
function isEven($number) {
    return $number % 2 === 0;
}

function divideWithoutRemainder($dividend, $divisor) {
    if ($divisor === 0) {
        throw new InvalidArgumentException('Деление на ноль');
    }
    $quotient = intdiv($dividend, $divisor);
    $remainder = $dividend - $quotient * $divisor;
    return [$quotient, $remainder];
}

list($q, $r) = divideWithoutRemainder(17, 5);
echo "Частное: $q, остаток: $r";
?>
Частное: 3, остаток: 2

Так можно вручную получить одновременно частное и остаток, если это необходимо.

Использование bcdiv для чисел за пределами int

Пример
<?php
$a = '12345678901234567890';
$b = '987654321';
$result = bcdiv($a, $b, 0);
echo $result; // 12499999, в виде строки
?>
12499999

bcdiv позволяет работать с числами произвольной длины, не теряя точности. Это важно для финансовых и научных расчётов.

Деление без остатка в PHP - comments

En
без остатка php (php)