По модулю в JavaScript - большое количество - PullRequest
15 голосов
/ 30 мая 2009

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

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

Result: 66

В чем здесь проблема?

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

Ответы [ 6 ]

13 голосов
/ 15 апреля 2013

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

9 голосов
/ 05 мая 2010

Несколько улучшений в версии Бенедикта: "cRest + = '' + cDivident;" это исправление; parseInt (делитель) позволяет передавать оба аргумента как строки; проверка на пустую строку в конце всегда возвращает числовые значения; добавлены операторы 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;
}
5 голосов
/ 30 мая 2009

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

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

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

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

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

4 голосов
/ 19 июля 2017

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

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

  • (a + b)% m = ((a% m) + (b% m))% m
  • (a-b)% m = ((a% m) - (b% m))% m
  • (a 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;
};
4 голосов
/ 18 июня 2009

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

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;
}
3 голосов
/ 15 декабря 2010

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

...