По модулю в JavaScript-большое число
Я пытаюсь вычислить с помощью функции JS по модулю, но не получаю правильный результат (который должен быть 1). Вот жестко закодированный фрагмент кода.
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
в чем проблема?
С уважением, Бенедикт!--2-->
6 ответов
куча улучшений в версии Бенедикта: "cRest + =" + cDivident; " является исправлением; parseInt(divisor) позволяет передавать оба аргумента в виде строк; проверка пустой строки в конце всегда возвращает числовые значения; добавлены операторы var, поэтому он не использует глобальные переменные; преобразован foreach в Старый Стиль, чтобы он работал в браузерах со старым Javascript; исправлен cRest == 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 обычный номер счета I заканчивается очень большим числом, содержащимся в строковом типе данных. Из этого большого числа я должен найти остальное, когда разделен на 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;
}
Silent Matt разработал Javascript библиотека для больших целых чисел. Это могло бы решить и эту проблему.
для тех, кто просто хочет скопировать и вставить рабочее (функциональное) решение в 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
- (ab)%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;
};