Как выполнить целочисленное деление и получить остаток в JavaScript
В JavaScript, как можно:
- Рассчитать целочисленное частное при делении одного целого числа на другое?
- Получить остаток от операции деления?
Какие встроенные операторы или методы доступны для этих операций, и как они работают с разными типами чисел?
В JavaScript вы можете выполнять целочисленное деление с помощью функций Math.floor() или Math.trunc(), чтобы получить целую часть частного, и получать остаток с помощью оператора %. При целочисленном делении Math.floor() округляет вниз, а Math.trunc() просто удаляет дробную часть, с разным поведением для отрицательных чисел. Оператор остатка % возвращает остаток от деления одного операнда на другой, всегда принимая знак делимого.
Содержание
- Методы целочисленного деления
- Операции с остатком и модулем
- Работа с отрицательными числами
- Вопросы производительности
- Практические примеры
Методы целочисленного деления
В JavaScript нет встроенного оператора целочисленного деления, как в некоторых других языках, поэтому для получения целой части частного нужно использовать специальные методы. Вот основные подходы:
Math.floor() для целочисленного деления
Math.floor() всегда округляет вниз до ближайшего целого числа, что делает его подходящим для положительных чисел:
const quotient = Math.floor(7 / 3); // Возвращает 2
const quotient2 = Math.floor(10 / 3); // Возвращает 3
Согласно документации MDN, Math.floor() возвращает наибольшее целое число, которое меньше или равно заданному числу.
Math.trunc() для целочисленного деления
Math.trunc() просто удаляет дробную часть без округления:
const quotient = Math.trunc(7 / 3); // Возвращает 2
const quotient2 = Math.trunc(10 / 3); // Возвращает 3
Как объясняется в GoLinuxCloud, “метод trunc просто возвращает целую часть числа и удаляет любые дробные цифры, присутствующие в значении Number”.
Побитовые операторы
Для небольших чисел можно использовать побитовые операторы, которые обеспечивают лучшую производительность:
const quotient = ~~(7 / 3); // Возвращает 2
const quotient2 = ~~(10 / 3); // Возвращает 3
В статье Delft Stack отмечается, что “производительность побитовых операторов выше, чем у функций библиотеки Math, но способность обрабатывать большие числа ниже. Поэтому, если у вас небольшие числа, можно использовать побитовые операторы; в противном случае используйте функции библиотеки Math, такие как Math.floor и Math.trunc”.
Операции с остатком и модулем
Оператор остатка (%)
JavaScript предоставляет оператор % для получения остатка от операции деления:
const remainder = 7 % 3; // Возвращает 1
const remainder2 = 10 % 3; // Возвращает 1
Согласно документации MDN об операторе остатка, “оператор остатка (%) возвращает остаток, оставшийся после деления одного операнда на другой”.
Вычисление частного и остатка за одну операцию
Вы можете вычислить как целочисленное деление, так и остаток за одну операцию:
const dividend = 13;
const divisor = 5;
const quotient = Math.floor(dividend / divisor); // 2
const remainder = dividend % divisor; // 3
В статье wikitechy предлагается альтернативный подход: var remainder = x % y; return (x - remainder) / y;
Работа с отрицательными числами
Различное поведение с отрицательными числами
Различные методы целочисленного деления ведут себя по-разному при работе с отрицательными числами:
// Поведение Math.floor()
console.log(Math.floor(-7 / 3)); // Возвращает -3 (округляет вниз)
// Поведение Math.trunc()
console.log(Math.trunc(-7 / 3)); // Возвращает -2 (удаляет дробную часть)
// Поведение побитового оператора
console.log(~~(-7 / 3)); // Возвращает -2
Как объясняет Codemia, “при работе с отрицательными числами, возможно, вы захотите использовать Math.trunc(), который просто обрезает десятичную часть без округления”.
Оператор остатка с отрицательными числами
Оператор % принимает знак делимого:
console.log(7 % 3); // Возвращает 1
console.log(-7 % 3); // Возвращает -1 (знак делимого)
console.log(7 % -3); // Возвращает 1 (знак делимого)
console.log(-7 % -3); // Возвращает -1 (знак делимого)
В статье GeeksforGeeks говорится, что “JavaScript %(модуль) ведет себя как операция остатка и возвращает остаток, и поскольку число отрицательно, остаток также получается отрицательным”.
Истинный модуль против остатка
Оператор % в JavaScript технически является оператором остатка, а не истинным оператором модуля. Истинный модуль всегда возвращает положительный результат:
// Вычисление истинного модуля
function trueModulo(dividend, divisor) {
const remainder = dividend % divisor;
return remainder >= 0 ? remainder : remainder + divisor;
}
console.log(trueModulo(-7, 3)); // Возвращает 2 (истинный модуль)
console.log(-7 % 3); // Возвращает -1 (остаток)
Как объясняется в 2ality.com, “если и делимое, и делитель положительны, оператор модуля дает те же результаты, что и оператор остатка. Если же у делимого и делителя разные знаки, то результаты будут разными”.
Вопросы производительности
Производительность побитовых операторов
Побитовые операторы, такие как ~~, обеспечивают лучшую производительность для небольших чисел:
// Тест производительности
console.time('Math.floor');
for (let i = 0; i < 1000000; i++) Math.floor(i / 3);
console.timeEnd('Math.floor');
console.time('Bitwise');
for (let i = 0; i < 1000000; i++) ~~(i / 3);
console.timeEnd('Bitwise');
Однако, как отмечалось ранее, побитовые операторы имеют ограничения при работе с большими числами. В статье Delft Stack предупреждается, что “если у вас небольшие числа, можно использовать побитовые операторы; в противном случае используйте функции библиотеки Math, такие как Math.floor и Math.trunc”.
Math.trunc() против Math.floor()
Math.trunc() обычно предпочтительнее, чем Math.floor() для целочисленного деления, потому что:
- Он работает последовательно как с положительными, так и с отрицательными числами, когда вам нужно просто удалить дробную часть
- Он не引入ет поведение округления, которое может быть неожиданным
- Он был введен в ES6, что делает его более современным подходом
Практические примеры
Пример базового целочисленного деления
function integerDivision(dividend, divisor) {
if (divisor === 0) throw new Error('Деление на ноль');
return Math.trunc(dividend / divisor);
}
console.log(integerDivision(13, 5)); // 2
console.log(integerDivision(-13, 5)); // -2
console.log(integerDivision(13, -5)); // -2
Функция полного деления
function divide(dividend, divisor) {
if (divisor === 0) throw new Error('Деление на ноль');
const quotient = Math.trunc(dividend / divisor);
const remainder = dividend % divisor;
return {
quotient,
remainder,
trueModulo: remainder >= 0 ? remainder : remainder + divisor
};
}
console.log(divide(13, 5));
// { quotient: 2, remainder: 3, trueModulo: 3 }
console.log(divide(-13, 5));
// { quotient: -2, remainder: -3, trueModulo: 2 }
Пример обработки массива
function distributeItems(totalItems, people) {
if (people <= 0) throw new Error('Количество людей должно быть положительным');
const itemsPerPerson = Math.floor(totalItems / people);
const remainderItems = totalItems % people;
return {
itemsPerPerson,
remainderItems,
distribution: Array(people).fill(itemsPerPerson).map((items, index) =>
index < remainderItems ? items + 1 : items
)
};
}
console.log(distributeItems(10, 3));
// {
// itemsPerPerson: 3,
// remainderItems: 1,
// distribution: [4, 3, 3]
// }
Заключение
Ключевые выводы
-
Целочисленное деление: Используйте
Math.trunc()для последовательного поведения как с положительными, так и с отрицательными числами, илиMath.floor(), если вам специально нужно округление вниз. -
Операция остатка: Оператор
%возвращает остаток и принимает знак делимого. Для истинного поведения модуля требуются дополнительные вычисления. -
Отрицательные числа: Имейте в виду, что разные методы ведут себя по-разному с отрицательными числами -
Math.trunc()удаляет дробные части, аMath.floor()округляет вниз. -
Производительность: Побитовые операторы, такие как
~~, обеспечивают лучшую производительность для небольших чисел, но имеют ограничения при работе с большими числами. -
Возможности ES6:
Math.trunc()был введен в ES6 и обеспечивает более последовательный подход к целочисленному делению.
Практические рекомендации
- В большинстве случаев используйте
Math.trunc()для целочисленного деления, так как он обеспечивает последовательное поведение - Используйте оператор
%для операций с остатком - Будьте внимательны к различиям в поведении методов с отрицательными числами
- Используйте побитовые операторы только тогда, когда производительность критична и вы работаете с небольшими числами
- Реализуйте логику истинного модуля, когда вам нужны положительные остатки
Связанные вопросы
- В чем разница между остатком и модулем в JavaScript?
- Как обрабатывать деление на ноль в JavaScript?
- Какой метод быстрее для целочисленного деления в JavaScript?
Источники
- How to perform an integer division, and separately get the remainder, in JavaScript - Stack Overflow
- Division in JavaScript - GeeksforGeeks
- Integer Division and Finding the Remainder in JavaScript - Stackabuse
- Integer Division in JavaScript | Delft Stack
- JavaScript Integer Division [3 Methods] | GoLinuxCloud
- Codemia | How to perform an integer division, and separately get the remainder, in JavaScript
- Integer division in JavaScript explained - DEV Community
- JavaScript Integer Division: Examples and Tips - SkillReactor Blog
- javascript tutorial - How to perform integer division and get the remainder we javascript ? - wikitechy
- Division (/) - JavaScript | MDN
- JavaScript % (modulo) gives a negative result for negative numbers - Stack Overflow
- How to get negative result using modulo operator in JavaScript ? - GeeksforGeeks
- Understanding the JavaScript Modulo Operator - Reddit
- The Modulus Operator in JavaScript - Mastering JS
- JavaScript Remainder(%) Operator - GeeksforGeeks
- How does Javascript handle a negative modulo? (
-5 % 20) - Codecademy Forums - Remainder (%) - JavaScript | MDN
- Remainder operator vs. modulo operator (with JavaScript code) - 2ality.com