Как выполнить целочисленное деление и отдельно получить остаток в JavaScript?

В JavaScript, как получить:

  1. Сколько раз одно целое число переходит в другое?
  2. Остаток?

person Yarin    schedule 19.11.2010    source источник


Ответы (17)


Для некоторого числа y и некоторого делителя x вычислить частное (quotient) и остаток (remainder) как:

var quotient = Math.floor(y/x);
var remainder = y % x;
person Mark Elliot    schedule 19.11.2010
comment
% работает с числами с плавающей запятой в JavaScript (это отличается от многих других языков), что, возможно, нежелательно: 3.5 % 2 оценивается как 1,5. Не забудьте обработать (parseInt, floor и т. Д.) По мере необходимости - person ; 19.11.2010
comment
Целая часть -4,5 в математике равна -5, так как -5 - это максимально возможное целое число, которое все еще меньше -4,5. - person Toughy; 03.12.2014
comment
Однако, что бы вы ни решили делать с отрицательными числами, оно должно быть согласованным в отношении частного и остатка. Таким образом, совместное использование floor и % несовместимо. Либо используйте trunc вместо floor (тем самым разрешая отрицательные остатки), либо используйте вычитание, чтобы получить остаток (rem = y - div * x). - person Mark Reed; 17.02.2016
comment
1. Если вы все равно собираетесь вычислить остаток rem, вы можете получить частное div быстрее без покрытия: (y - rem) / x. 2. Между прочим, операцию по модулю в соответствии с рекомендуемым определением Дональда Кнута (знак-совпадение-делитель, а не остаток, то есть евклидов модуль, ни знак-совпадение-делимое в JavaScript) - это то, что мы можем закодировать в JavaScript как function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }. - person Aaron Mansheim; 06.02.2017
comment
@MarkReed, Toughy: Учитывая описание в вопросе, я не понимаю, как 2 может превратиться в -9 всего -5 раз. Не могли бы вы объяснить? - person spanky; 21.08.2017
comment
-9 / 2 = -4,5. Затем вы берете пол -4,5, что составляет -5. Помните, что -5 меньше -4,5, а операция нижнего предела определяется как наибольшее целое число, меньшее заданного значения. - person Mark Reed; 22.08.2017
comment
Обратите внимание, что в общем случае наличие -3 по модулю 5 равняется 2 вместо -3, может быть неожиданным, но это более полезно с математической точки зрения, поскольку позволяет избежать любых разрывов в районе 0; любое целое число по модулю положительного n всегда находится в диапазоне [0, n-1], независимо от того, является ли начальное целое положительным или отрицательным. Но чтобы согласиться с этим определением и сохранить тождество quotient * divisor + remainder = dividend истинным, частное должно быть минимальным. - person Mark Reed; 22.08.2017
comment
@spanky См. Википедию для получения дополнительных сведений о трех типах деления по модулю (и целочисленного деления). - person Franklin Yu; 17.05.2018
comment
Внимание, это не сработало с отрицательным числом, потому что -9 % 2 это -1 вместо 1. - person ramwin; 02.01.2019
comment
@ user166390 все числа в javascript являются числами с плавающей запятой - person ICW; 21.03.2021

Я не разбираюсь в побитовых операторах, но вот еще один способ получить целое число:

var num = ~~(a / b);

Это будет правильно работать и для отрицательных чисел, в то время как Math.floor() будет округляться в неправильном направлении.

Это тоже кажется правильным:

var num = (a / b) >> 0;
person user113716    schedule 19.11.2010
comment
Другой, цель которого я только что потратил последние 20 минут, пытаясь понять, очевидно a/b | 0 - person BlueRaja - Danny Pflughoeft; 26.03.2011
comment
@ user113716 @BlueRaja Побитовые операции имеют смысл только с целочисленными типами, и JS (конечно) это знает. ~~int, int | 0 и int >> 0 не изменяют начальный аргумент, но заставляют интерпретатор передавать оператору неотъемлемую часть. - person Aleksei Zabrodskii; 15.07.2012
comment
На всякий случай, если кому-то интересно, что было быстрее всего: jsperf.com/integer- Division-math-floor-ab-vs-ab (результаты спойлера неубедительны). - person jonasfj; 24.12.2012
comment
floor вряд ли поворачивает в неправильном направлении, учитывая его название - просто не то направление, которого обычно хотят люди! - person Mark K Cowan; 19.12.2013
comment
Это буу буу. a = 12447132275286670000; b = 128 Math.floor(a/b) - ›97243220900677100 и ~~(a/b) -› -1231452688. - person Mirek Rusin; 26.03.2014
comment
Будьте осторожны с приоритетом. ~~(5/2) --> 2, как и (5/2)>>0 --> 2, но ~~(5/2) + 1 --> 3, а ~~(5/2)>>0 + 1 --> 1. ~~ - хороший выбор, потому что приоритет более уместен. - person timkay; 29.05.2014
comment
нежелательное поведение >>0, поэтому emscripten и asm.js используют |0 - person technosaurus; 31.07.2014
comment
просто для пояснения - они действительно работают, потому что они не работают, и все побитовые операции js преобразуются в 32-битные целые числа - person JonnyRaa; 17.09.2014
comment
Согласен с Джонни Лидсом. Фактически, хотя это решение заслуживает упоминания, я бы отклонил его как лучшую практику кодирования. В ответе Марка Эллиота используется функция, предоставленная для этой цели. Этот ответ основан на поведении, которое не гарантируется и не предполагается реализацией побитовых операций. - person Mark Goldfain; 22.11.2014
comment
Ответы: buubuus ~~ (2147483648/1) = -2147483648 (2147483648/1) ›› 0 = -2147483648 - person Chihung Yu; 07.05.2015
comment
отлично подходит в контексте, где у вас нет математической библиотеки (в моем случае в шаблонах) - person vincent; 31.08.2015
comment
Этот ответ работает для чисел, которые попадают в диапазон целого числа со знаком, поскольку Javascript использует только 32 младших бита для побитовых операций. Однако OP спросил о целочисленных операциях, а целые числа на самом деле являются 32-битными числами со знаком на большинстве языков (JS фактически не имеет целых чисел), поэтому я думаю, что это не проблема. Да, это не сработает для очень больших чисел, но также будет Math.floor, когда числа превышают 53 бита ... Это просто неотъемлемые ограничения, присутствующие повсюду. Если вы хотите сделать это для произвольно больших чисел, вам понадобится библиотека bigint / bignumber. - person Stijn de Witt; 27.11.2015
comment
Я бы не сказал, что Math.floor округляет отрицательное частное в неправильном, а скорее в другом направлении. Math.floor(-3 / 10) === -1 тогда будет соответствовать делению по полу (округляет вниз), тогда как ~~(-3 / 10) === 0 соответствует усеченному делению (округляет до нуля ). См. Wiki: операция по модулю. - person mucaho; 18.03.2016
comment
По сути, это обфускация кода. Не делайте этого, чтобы быть умным, используйте немного более длинный, но более читаемый Math.floor или новый Math.trunc ES6 (Edge 12+) - person fregante; 30.05.2016
comment
@ bfred.it Большинство разработчиков уже принимают использование | 0 для усечения, особенно из-за его использования в asm.js, поэтому вы не можете точно сказать, что он запутывает код, потому что его значение уже широко известно. - person Shien; 24.09.2016
comment
Я комментировал ответ, и в нем не упоминается |0. Также не имеет значения, что asm.js использует определенный стиль, поскольку он предназначен не для записи / чтения людьми, а для транспиляторов и браузеров. - person fregante; 25.09.2016
comment
@ bfred.it Идк. Тернары выглядят странно, когда вы их впервые видите. Нулевые условные выражения также поначалу выглядят очень странно. Никто не говорит не использовать их, потому что они кажутся умными; вместо этого они представляют собой новые языковые дополнения, которые, как ожидается, должны выучить разработчики. Если ~~ или | 0 еще не существовали, у кого-то могло возникнуть искушение добавить их. Как сказал Джоэл, старый код не ржавеет . Не используйте существующие полезные соглашения просто потому, что они старые. Это хороший. - person ruffin; 24.03.2017
comment
Есть ли какой-то контекст разработчика вокруг термина buu buu, о котором я не знаю? Полагаю, мы не говорим о навыке Dragonball Z или детской линии одежды? - person Mike Devenney; 20.04.2017
comment
@ BlueRaja-DannyPflughoeft Применяя таким образом побитовое ИЛИ с плавающей точкой, вы в основном делаете ставку на незрелость JavaScript. Python3 вызовет ошибку TypeError: unsupported operand type(s) for |: 'float' and 'int' - person Serge Stroobandt; 30.03.2021
comment
Но помните, что побитовые операции предназначены только для 32-битных целых чисел. - person 0zkr PM; 23.06.2021

Я сделал несколько тестов скорости в Firefox.

-100/3             // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34,       0.5016 millisec
~~(-100/3)         // -33,       0.3619 millisec
(-100/3>>0)        // -33,       0.3632 millisec
(-100/3|0)         // -33,       0.3856 millisec
(-100-(-100%3))/3  // -33,       0.3591 millisec

/* a=-100, b=3 */
a/b                // -33.33..., 0.4863 millisec
Math.floor(a/b)    // -34,       0.6019 millisec
~~(a/b)            // -33,       0.5148 millisec
(a/b>>0)           // -33,       0.5048 millisec
(a/b|0)            // -33,       0.5078 millisec
(a-(a%b))/b        // -33,       0.6649 millisec

Вышеупомянутое основано на 10 миллионах испытаний для каждого.

Вывод: используйте (a/b>>0) (или (~~(a/b)) или (a/b|0)), чтобы добиться повышения эффективности примерно на 20%. Также имейте в виду, что все они несовместимы с Math.floor, когда a/b<0 && a%b!=0.

person KalEl    schedule 20.06.2013
comment
Я считаю, что Math.floor () имеет более стабильную производительность, чем другие. это меньше взлетов и падений - person Henry Leu; 12.09.2013
comment
Обратите внимание, что оптимизация целочисленного деления для скорости имеет смысл, только если вы делаете это много. В любом другом случае я бы порекомендовал выбрать самый простой (какой кажется вам и вашим коллегам самым простым). - person mik01aj; 08.01.2014
comment
@ m01 полностью согласен - в Интернете слишком много внимания уделяется подобным вещам - person JonnyRaa; 17.09.2014
comment
@ m01 Но что сложнее: узнать о Math.floor и неизвестно сколько других функциях API или узнать об операторе ~ (побитовое-не) и о том, как побитовые операции работают в JS, а затем понять эффект двойной тильды? - person Stijn de Witt; 27.11.2015
comment
Что ж, если ваши коллеги не программируют микросхемы на ассемблере, они, вероятно, поймут Math.floor лучше. И даже если нет, этот можно гуглить. - person mik01aj; 28.11.2015
comment
| 0: 2582,521 мс ~~: 2631,974 мс Math.floor: 2382,893 мс. Я рекомендую вам выполнить тесты самостоятельно, plnkr.co/edit/9g0IXjpavR2t2d2L1DC0 - person Peheje; 15.10.2016
comment
@JonnyLeeds Я пришел сюда в поисках целочисленного деления в Javascript, что не является нишевым требованием. - person Mark Green; 09.08.2017
comment
@MarkGreen да, но просто желание сделать это не означает, что вы должны писать его в странной форме только потому, что это оказывается самым быстрым, без уважительной причины - ясность кода в целом обычно должна быть вашей первой заботой. Кроме того, эти тесты могут быть совершенно бессмысленными после смены языка и в разных браузерах - вам нужно будет профилировать, чтобы узнать, что медленно в вашем приложении. Маловероятно, что это будет ваш метод целочисленного деления, если вы еще не оптимизировали что-то еще! - person JonnyRaa; 20.09.2017
comment
Осторожно, все побитовые операции работают только с 32-битными числами. - person k06a; 18.06.2020
comment
Что касается удобочитаемости, я только что попросил кого-то спросить, что делает |0, поскольку это выглядит как нерабочий… «Ага, это преобразование в int», будучи четким и прямым ответом, заставляет меня быть поклонником этого выбора - person JamesTheAwesomeDude; 22.09.2020
comment
@JonnyRaa Хороший код быстро и легко понять. Вообще говоря, оптимизация среды выполнения JavaScript, такой как V8, будет лучше, если вы инкапсулируете чувствительный к производительности код в функцию, потому что это означает, что им нужно только оценить код внутри этой функции, чтобы оптимизировать ее. Вы можете написать очень хорошо задокументированную функцию fast_integer_divide с помощью побитовых хаков, а затем везде в коде вы видите fast_integer_divide, который даже четче, чем Math.floor, и НАМНОГО быстрее (в 5 раз) в моих тестах. Разборчивость кода очень важна, но, пожалуйста, не поощряйте людей жертвовать производительностью. - person Sam Claus; 04.12.2020
comment
Math.floor по-прежнему не работает. Спасибо за работу. - person Display name; 12.02.2021
comment
Это сравнение производительности методов целочисленного деления, а не ответ на вопрос. - person mikemaccana; 02.03.2021
comment
Применяя таким образом побитовые операции с плавающей точкой, вы в основном делаете ставку на незрелость JavaScript. Python3 вызовет ошибку TypeError: unsupported operand type(s) for |: 'float' and 'int' - person Serge Stroobandt; 30.03.2021
comment
Для начала, если для вашего приложения важны доли миллисекунд, JavaScript не кажется лучшим выбором языка. Но если у вас есть случай, когда производительность действительно важнее удобочитаемости, и вы застряли с JS, имейте в виду, что производительность не одинакова для всех платформ. Я был бы удивлен, если бы эта конкретная оптимизация стоила ресурсов команды разработчиков, но если бы это было так, интерпретатор, автоматически выполняющий Math.floor(a/b) побитовую операцию, кажется достаточно простым. - person Michael Scheper; 21.06.2021
comment
Повышение эффективности на 20%. Вы опубликовали результаты, которые показывают разницу в десятые доли миллисекунд. Это как если бы мой босс хвастался, что только что повысил мне зарплату на 0,001%. Если увеличение производительности на десятые доли миллисекунд полезно для вас, просто обновите сервер, это будет дешевле, чем время разработки, и вы получите в десять раз большее улучшение. - person James; 03.07.2021

ES6 представляет новый метод Math.trunc. Это позволяет исправить ответ @ MarkElliot, чтобы он работал и для отрицательных чисел:

var div = Math.trunc(y/x);
var rem = y % x;

Обратите внимание, что Math методы имеют преимущество перед побитовыми операторами в том, что они работают с числами, превышающими 2 31.

person Oriol    schedule 10.03.2014
comment
var y = 18014398509481984; var x = 5; div =? - ошибка ? - person 4esn0k; 03.02.2015
comment
@ 4esn0k Это не ошибка. В вашем номере слишком много цифр, у вас не может быть такой точности в 64-битном двоичном формате числа IEEE 754. Например, 18014398509481984 == 18014398509481985. - person Oriol; 03.02.2015
comment
18014398509481984 == 2 ** 54, и я специально использовал это число, потому что оно представлено именно в формате binary64. и ответ тоже представлен точно - person 4esn0k; 03.02.2015
comment
@ 4esn0k Я не очень хорошо объяснил. Я имел в виду 18014398509481984 / 5 это 3602879701896396.8. Однако его нельзя сохранить, поэтому он преобразуется в 3602879701896397. И тогда Math.trunc(3602879701896397) это 3602879701896397. - person Oriol; 03.02.2015
comment
Хорошо, я потратил целый день, думая, как обойти это округление. Кажется, можно определить, что произошло округление и исправить усеченный цитатник: if (y / x === div && rem ›x - rem) {div - = 1; }, но я не уверен в правильности, да ладно, ваше решение достаточно для большинства случаев. - person 4esn0k; 03.02.2015
comment
Думаю, выбор прост: вам нужна поддержка чисел до 32 бит со знаком? Используйте 1_. Требуется поддержка больших чисел до 54 бит со знаком? Используйте Math.trunc, если он у вас есть, или Math.floor в противном случае (с поправкой на отрицательные числа). Нужно поддерживать еще большие числа? Используйте какую-нибудь большую библиотеку чисел. - person Stijn de Witt; 27.11.2015
comment
для рубистов сюда из гугла в поисках divmod можно реализовать как таковое: function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; } - person Alex Moore-Niemi; 25.11.2016

Обычно я использую:

const quotient =  (a - a % b) / b;
const remainder = a % b;

Наверное, не самый элегантный, но работает.

person Wolf Elkan    schedule 19.05.2017
comment
Хорошее решение, потому что оно позволяет избежать уродливого синтаксического анализа или усечения поплавка. - person Dem Pilafian; 20.03.2019
comment
если вам нужны как частное, так и остаток, сначала вычислите остаток, а затем повторно используйте это значение в выражении для частного, то есть частное = (a - остаток) / b; - person gb96; 04.04.2019
comment
остаток = a% b; частное = (a - остаток) / b; - person Zv_oDD; 30.10.2019

Вы можете использовать функцию parseInt, чтобы получить усеченный результат.

parseInt(a/b)

Чтобы получить остаток, используйте оператор мода:

a%b

parseInt имеет некоторые подводные камни со строками, чтобы избежать использования параметра radix с основанием 10

parseInt("09", 10)

В некоторых случаях строковое представление числа может быть научной записью, в этом случае parseInt выдаст неверный результат.

parseInt(100000000000000000000000000000000, 10) // 1e+32

Результатом этого вызова будет 1.

person Édipo Costa Rebouças    schedule 13.04.2015
comment
parseInt по возможности следует избегать. Вот предупреждение Дугласа Крокфорда: если первый символ строки равен 0, тогда строка оценивается по базе 8, а не по базе 10. В базе 8, 8 и 9 не являются цифрами, поэтому parseInt (08) и parseInt (09) производят 0 в качестве своего результата. Эта ошибка вызывает проблемы в программах, анализирующих дату и время. К счастью, parseInt может принимать параметр radix, так что parseInt (08, 10) дает 8. Я рекомендую всегда указывать параметр radix. archive.oreilly.com/pub/ а / javascript / выдержки / - person Powers; 02.11.2015
comment
При делении я ожидаю получить число, а не строку, но это хороший момент. - person Édipo Costa Rebouças; 25.11.2015
comment
@Powers, так что добавьте основание. Он не говорит, что parseInt следует избегать; просто нужно знать о некоторых подводных камнях. Вы должны знать об этом и быть готовым к тому, чтобы справиться с этим. - person None; 22.12.2015
comment
Никогда не вызывайте parseInt с числовым аргументом. parseInt должен анализировать частично числовые строки, а не усекать числа. - person Oriol; 16.06.2016
comment
То, что вещи изначально не предназначены для использования определенным образом, не означает, что вы не должны этого делать. Этот ответ работает. - person fregante; 25.03.2017

Math.floor(operation) возвращает округленное в меньшую сторону значение операции.

Пример 1 st вопроса:

var x = 5;
var y = 10.4;
var z = Math.floor(x + y);

console.log(z);

Консоль:

15

Пример 2 nd вопроса:

var x = 14;
var y = 5;
var z = Math.floor(x%y);

console.log(x);

Консоль:

4

person Aetricity    schedule 01.11.2014

JavaScript вычисляет нижний предел отрицательных чисел и остаток нецелых чисел, следуя математическим определениям для них.

FLOOR определяется как «наибольшее целое число, меньшее, чем параметр», таким образом:

  • положительные числа: FLOOR (X) = целая часть X;
  • отрицательные числа: FLOOR (X) = целая часть X минус 1 (потому что она должна быть МЕНЬШЕ, чем параметр, т.е. более отрицательной!)

REMAINDER определяется как «остаток» от деления (евклидова арифметика). Когда делимое не является целым числом, частное обычно также не является целым числом, т. Е. Нет остатка, но если частное принудительно должно быть целым числом (и это то, что происходит, когда кто-то пытается получить остаток или модуль число с плавающей запятой), очевидно, останется нецелое число.

JavaScript действительно рассчитывает все, как ожидалось, поэтому программист должен быть осторожен, задавая правильные вопросы (и люди должны быть осторожны, чтобы отвечать на то, что задают!) Первый вопрос Ярина НЕ был «каково целочисленное деление X на Y», но, вместо этого "ВСЕ раз, когда данное целое число ВХОДИТ В другое". Для положительных чисел ответ одинаков для обоих, но не для отрицательных чисел, потому что целочисленное деление (делимое на делитель) будет на -1 меньше, чем количество раз, когда число (делитель) «переходит» в другое (делимое). Другими словами, FLOOR вернет правильный ответ при целочисленном делении отрицательного числа, но Ярин этого не спрашивал!

gammax ответил правильно, этот код работает так, как просил Ярин. С другой стороны, Самуэль ошибается, я думаю, он не занимался математикой, иначе он бы увидел, что это действительно работает (кроме того, он не сказал, что было делителем в его примере, но я надеюсь, что это было 3):

Остаток = X% Y = -100% 3 = -1

GoesInto = (X - остаток) / Y = (-100 - -1) / 3 = -99 / 3 = -33

Кстати, я тестировал код на Firefox 27.0.1, он работал, как ожидалось, с положительными и отрицательными числами, а также с нецелыми значениями, как для делимого, так и для делителя. Пример:

-100,34 / 3,57: GoesInto = -28, остаток = -0,3800000000000079

Да, я заметил, там есть проблема с точностью, но у меня не было времени проверить это (я не знаю, проблема ли это в Firefox, Windows 7 или с FPU моего процессора). Однако на вопрос Ярина, который включает только целые числа, код gammax работает отлично.

person Cyberknight    schedule 27.02.2014

Ответ Алекса Мур-Ниеми в качестве ответа:

Для рубистов из Google в поисках divmod вы можете реализовать это как таковое:

function divmod(x, y) {
  var div = Math.trunc(x/y);
  var rem = x % y;
  return [div, rem];
}

Результат:

// [2, 33]
person Alex    schedule 06.07.2017
comment
Обычно divmod использует деление по полу (Math.floor), которое отличается от усеченного деления (Math.trunc), когда задействованы отрицательные числа. Это касается пакета NPM divmod, Ruby divmod, SWI-Prolog divmod и, вероятно, многие другие реализации тоже. - person Palec; 07.07.2017
comment
Усеченное деление дает более естественные результаты, чем деление по полу, но совместимость превосходит это, ИМО. Возможно, есть математические или производственные причины для использования напольного деления. Обратите внимание, что обычно divmod существует, потому что он выполняется в два раза быстрее, чем вычисление двух операций по отдельности. Предоставление такой функции без этого преимущества в производительности может сбивать с толку. - person Palec; 07.07.2017

const idivmod = (a, b) => [a/b |0, a%b];

есть также предложение, работающее над этим Модуль и дополнительная целочисленная математика

person nkitku    schedule 25.11.2020

Если вы просто делите степень двойки, вы можете использовать побитовые операторы:

export function divideBy2(num) {
  return [num >> 1, num & 1];
}

export function divideBy4(num) {
  return [num >> 2, num & 3];
}

export function divideBy8(num) {
  return [num >> 3, num & 7];
}

(Первое - частное, второе - остаток)

person Konstantin Möllers    schedule 13.09.2017
comment
Обычно function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }. - person Palec; 13.09.2017

Подсчитать количество страниц можно за один шаг: Math.ceil (x / y)

person user1920925    schedule 11.11.2017
comment
Я не понимаю, как это обеспечивает остаток. - person Paul Rooney; 19.12.2018

Вы можете использовать тернарность, чтобы решить, как обрабатывать положительные и отрицательные целые числа.

var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1

Если число положительное, все в порядке. Если число отрицательное, оно добавит 1 из-за того, как Math.floor обрабатывает негативы.

person John Galt    schedule 08.06.2015

Это всегда будет усекаться до нуля. Не уверен, что уже слишком поздно, но вот оно:

function intdiv(dividend, divisor) { 
    divisor = divisor - divisor % 1;
    if (divisor == 0) throw new Error("division by zero");
    dividend = dividend - dividend % 1;
    var rem = dividend % divisor;
    return { 
        remainder: rem, 
        quotient: (dividend - rem) / divisor
    };
}
person bzim    schedule 11.05.2017

Если вам нужно вычислить остаток для очень больших целых чисел, которые среда выполнения JS не может представить как таковые (любое целое число больше 2 ^ 32 представляется как число с плавающей запятой и поэтому теряет точность), вам нужно проделать некоторую уловку.

Это особенно важно для проверки многих контрольных цифр, которые присутствуют во многих случаях нашей повседневной жизни (номера банковских счетов, кредитные карты, ...)

В первую очередь вам нужен ваш номер в виде строки (иначе вы уже потеряли точность, а остаток не имеет смысла).

str = '123456789123456789123456789'

Теперь вам нужно разделить вашу строку на более мелкие части, достаточно маленькие, чтобы объединение любого остатка и части строки могло уместиться в 9 цифрах.

digits = 9 - String(divisor).length

Подготовьте регулярное выражение для разделения строки

splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')

Например, если digits равно 7, регулярное выражение будет

/.{1,7}(?=(.{7})+$)/g

Он соответствует непустой подстроке максимальной длины 7, за которой следует ((?=...) - положительный просмотр вперед) количество символов, кратное 7. 'g' заставляет выражение проходить через всю строку, не останавливаясь при первом совпадении. .

Теперь преобразуйте каждую часть в целое число и вычислите остаток на reduce (добавив предыдущий остаток - или 0 - умноженный на правильную степень 10):

reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor

Это будет работать благодаря алгоритму "вычитания" остатка:

n mod d = (n - kd) mod d

который позволяет заменить любую «начальную часть» десятичного представления числа его остатком, не влияя на конечный остаток.

Окончательный код будет выглядеть так:

function remainder(num, div) {
  const digits = 9 - String(div).length;
  const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
  const mult = Math.pow(10, digits);
  const reducer = (rem, piece) => (rem * mult + piece) % div;

  return str.match(splitter).map(Number).reduce(reducer, 0);
}
person rewritten    schedule 19.09.2018

Вот способ сделать это. (Лично я бы не стал делать это таким образом, но подумал, что это интересный способ сделать это для примера)

function intDivide(numerator, denominator) {
  return parseInt((numerator/denominator).toString().split(".")[0]);
}

let x = intDivide(4,5);
let y = intDivide(5,5);
let z = intDivide(6,5);
console.log(x);
console.log(y);
console.log(z);

person Daniel    schedule 12.11.2020

person    schedule
comment
Эта версия, к сожалению, не проходит тест, когда x = -100, потому что она возвращает -34 вместо -33. - person Samuel; 07.12.2013
comment
как насчет var x = 0.3; var y = 0,01; ? (спасибо github.com/JuliaLang/julia/issues/4156#issuecomment-23324163) - person 4esn0k; 03.02.2015
comment
Фактически, @Samuel, с отрицательными значениями, этот метод возвращает правильные результаты или, по крайней мере, возвращает те же значения, что и метод, использующий Math.trunc :). Я проверил 100,3; -100,3; 100, -3 и -100, -3. Конечно, с момента вашего комментария прошло много времени, и все изменилось. - person Marjan Venema; 12.07.2018