Вопрос

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

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

Result: 66

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

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

Это было полезно?

Решение

Куча улучшений в версии Бенедикта:"cRest += " + cDivident;" - это исправление ошибки;parseInt(divisor) позволяет передавать оба аргумента в виде строк;проверка наличия пустой строки в конце позволяет всегда возвращать числовые значения;добавлены операторы var, поэтому он не использует глобальные переменные;преобразовал foreach в старый стиль, чтобы он работал в браузерах со старым Javascript;исправлен гребень == 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 с использованием обычного номера банковского счета я получаю очень большое число, содержащееся в строковом типе данных.Из этого большого числа я должен найти остальное при делении на 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;
}

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

Сайлент Мэтт разработал Javascript библиотека для Больших целых чисел.Это могло бы решить и эту проблему.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top