Модуль в JavaScript - большое количество

Я пытаюсь вычислить с помощью функции по модулю JS, но не получаю правильного результата (который должен быть равен 1). Вот жестко закодированный фрагмент кода.

var checkSum = 210501700012345678131468;
alert(checkSum % 97);

Result: 66

В чем проблема?

С уважением, Бенедикт


person Benedikt    schedule 30.05.2009    source источник


Ответы (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;
}
person Gilead    schedule 05.05.2010
comment
Небольшая ошибка/опечатка. Окончательное «cRest == 0» действительно должно быть «cRest = 0». - person Dan.StackOverflow; 29.03.2012
comment
Обратите внимание, что это по-прежнему не работает для чисел выше примерно 2**50 или что-то в этом роде. Не уверен, как с этим справиться, кроме как с помощью Python, где 2**99999 % 7 работает просто отлично. (Обратите внимание, что ** относится к возведению в степень, поэтому 2**8==256.) - person Luc; 24.06.2016

Для расчета IBAN из обычного номера банковского счета я получаю очень большое число, содержащееся в строковом типе данных. Из этого большого числа я должен найти остаток при делении на 97 -> большое число % 97.

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

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 (и некоторые) позиции максимального целого числа в JavaScript, в результате получается число больше 97, и это хорошее круглое число. Первые два аргумента имеют значение.

person Jaco Boon    schedule 15.04.2013

похоже, вы стали жертвой этого: Какое максимальное целочисленное значение в JavaScript, к которому может перейти число без потери точности?

просто чтобы повторить то, что в другой теме:

это 64-битные значения с плавающей запятой, наибольшее точное целочисленное значение равно 2^53. однако из раздела спецификации [8.5: Тип номера]:

Некоторые операторы ECMAScript работают только с целыми числами в диапазоне от -2^31 до 2^31-1 включительно или в диапазоне от 0 до 2^32-1 включительно. Эти операторы принимают любое значение типа Number, но сначала преобразуют каждое такое значение в одно из 2^32 целочисленных значений. См. описания операторов ToInt32 и ToUint32 в разделах 0 и 0 соответственно.

Но кредит, где кредит из-за. Джимми получил там принятый ответ за беготню (ну, погуглил).

person Jonathan Fingland    schedule 30.05.2009
comment
Итак, есть ли обходной путь для этого? Я не могу найти ничего полезного через Google. - person Benedikt; 30.05.2009
comment
Не могли бы вы сделать деление и вычислить остаток? - person gnarf; 30.05.2009
comment
учитывая, что приведенная выше контрольная сумма уже выше 2 ^ 53, вам придется сделать что-то еще .... интересное... разбить число до выполнения каких-либо операций над ним - person Jonathan Fingland; 31.05.2009

Для тех, кто просто хочет скопировать и вставить работающее (функциональное) решение в ES6 для проверки IBAN:

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;
};
person Ph. Wiget    schedule 19.07.2017

Наконец, мое решение:

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;
}
person Benedikt    schedule 17.06.2009

Компания Silent Matt разработала библиотеку Javascript для больших целых чисел. Это тоже может решить эту проблему.

person Jérôme Verstrynge    schedule 14.12.2010
comment
Но эта библиотека не содержит модульной функциональности, не так ли? - person Benedikt; 15.12.2010
comment
Да, смотрите divRem или остаток - person Jérôme Verstrynge; 19.12.2010