По модулю в JavaScript - большое число
-
06-09-2019 - |
Вопрос
Я пытаюсь вычислить с помощью функции JS по модулю, но не получаю правильного результата (который должен быть равен 1).Вот жестко запрограммированный фрагмент кода.
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
В чем здесь проблема?
С уважением, Бенедикт
Решение
Куча улучшений в версии Бенедикта:"cRest += " + cDivident;" - это исправление ошибки;parseInt(divisor) позволяет передавать оба аргумента в виде строк;проверка наличия пустой строки в конце позволяет всегда возвращать числовые значения;добавлены операторы var, поэтому он не использует глобальные переменные;преобразовал foreach в старый стиль, чтобы он работал в браузерах со старым Javascript;исправлен гребень == 0;ошибка (спасибо @Dan.StackOverflow).
function modulo (divident, divisor) { var cDivident = ''; var cRest = ''; for (var i in divident ) { var cChar = divident[i]; var cOperator = cRest + '' + cDivident + '' + cChar; if ( cOperator < parseInt(divisor) ) { cDivident += '' + cChar; } else { cRest = cOperator % divisor; if ( cRest == 0 ) { cRest = ''; } cDivident = ''; } } cRest += '' + cDivident; if (cRest == '') { cRest = 0; } return cRest; }
Другие советы
Для расчета IBAN с использованием обычного номера банковского счета я получаю очень большое число, содержащееся в строковом типе данных.Из этого большого числа я должен найти остальное при делении на 97 -> большое число% 97.
Как только я преобразую тип данных в целое число, я получаю переполнение, приводящее к отрицательному целому числу и, в конечном итоге, к неправильному значению rest.Когда я увидел несколько подробных фрагментов кода (которые также давали неверный результат), я не смог удержаться и поделился своими собственными.Кредиты идут на Нахождение модуля очень Большого числа при Нормальном числе
modulo: function(divident, divisor) {
var partLength = 10;
while (divident.length > partLength) {
var part = divident.substring(0, partLength);
divident = (part % divisor) + divident.substring(partLength);
}
return divident % divisor;
}
Н.Б.Я использую здесь 10 позиций, поскольку это меньше, чем 15 (и некоторые другие) позиций max integer в JavaScript, в результате получается число больше 97, и это хорошее круглое число.Первые два аргумента имеют значение.
похоже, ты стал жертвой этого: Каково наибольшее целочисленное значение JavaScript, к которому число может перейти без потери точности?
просто чтобы повторить то, что есть в другой теме:
это 64-битные значения с плавающей запятой, наибольшее точное целочисленное значение равно 2^ 53.однако из раздела спецификаций [8.5:Тип номера]:
Некоторые операторы ECMAScript имеют дело только с целыми числами в диапазоне от -2 ^31 до 2 ^ 31-1 включительно или в диапазоне от 0 до 2 ^ 32-1 включительно.Эти операторы принимают любое значение типа Number, но сначала преобразуют каждое такое значение в одно из 2 ^ 32 целых значений.Смотрите описания операторов ToInt32 и ToUint32 в разделах 0 и 0, соответственно
Но отдавайте должное там, где положено отдавать должное.Джимми получил общепринятый ответ за проделанную работу (ну, погуглил).
Наконец, мое решение:
function modulo (divident, divisor) {
cDivident = '';
cRest = '';
for each ( var cChar in divident ) {
cOperator = cRest + '' + cDivident + '' + cChar;
if ( cOperator < divisor ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) cRest = '';
cDivident = '';
}
}
return cRest;
}
Для тех, кто просто хочет скопировать и вставить рабочее (функциональное) решение в ES6 для проверки IBANs:
function isIBAN(s){
const rearranged = s.substring(4,s.length) + s.substring(0,4);
const numeric = Array.from(rearranged).map(c =>(isNaN(parseInt(c)) ? (c.charCodeAt(0)-55).toString() : c)).join('');
const remainder = Array.from(numeric).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % 97,0);
return remainder === 1;}
Вы могли бы даже написать это однострочно.
Операция по модулю выполняется над массивом целых чисел, хранящих фактическое число (divident
, применяется в качестве строки к функции):
function modulo(divident, divisor){
return Array.from(divident).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % divisor,0);
};
Это работает, потому что по модулю распределяется по сложению, вычитанию и умножению:
- (a+b)%m = ((a%m)+(b%m))%m
- (a-b)%m = ((a%m)-(b%m))%m
- (аb)%m = ((a%m)(b%m))%m
Функция IBAN, перенесенная в ES5, выглядит следующим образом:
function (s) {
var rearranged = s.substring(4, s.length) + s.substring(0, 4);
var numeric = Array.from(rearranged).map(function (c) { return (isNaN(parseInt(c)) ? (c.charCodeAt(0) - 55).toString() : c); }).join('');
var remainder = Array.from(numeric).map(function (c) { return parseInt(c); }).reduce(function (remainder, value) { return (remainder * 10 + value) % 97; }, 0);
return remainder === 1;
};
Сайлент Мэтт разработал Javascript библиотека для Больших целых чисел.Это могло бы решить и эту проблему.