По модулю в 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;
};