Если вам нужно вычислить остаток для очень больших целых чисел, которые среда выполнения 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);
}