Подтвердить что ты не робот

Modulo в JavaScript - большое количество

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

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

Result: 66

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

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

4b9b3361

Ответ 1

Множество улучшений версии Бенедикта: "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;
}

Ответ 2

Для формы расчета 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;
}

N.B. Здесь я использую 10 позиций, так как это меньше, чем 15 (и некоторые) положения max integer в JavaScript, это приводит к числу, превышающему 97, и это хороший круглый номер. Первые два аргумента имеют значение.

Ответ 3

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

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

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

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

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

Ответ 4

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

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;
}

Ответ 5

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

Ответ 6

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

Вы даже можете записать его как однострочный.

Операция modulo выполняется в массиве целых чисел, сохраняющих фактическое число (divident, применяемое как строка для функции):

function modulo(divident, divisor){
   return Array.from(divident).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % divisor,0);
};

Это работает, потому что Modulo является дистрибутивным над добавлением, вычитанием и умножением:

  • (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;
};