JavaScript中的Modulo - 大量的

时间:2009-05-30 15:15:39

标签: javascript integer modulo

我尝试用JS'模数函数计算,但是没有得到正确的结果(应该是1)。这是一段硬编码的代码。

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

Result: 66

这里的问题是什么?

此致 本尼迪克特

6 个答案:

答案 0 :(得分:13)

对于IBAN计算形式,正常的bankaccount数字我最终得到一个包含在字符串数据类型中的非常大的数字。从这个大数字我必须找到其余的除以97 - >大数%97。

一旦我将数据类型转换为整数,我就会得到一个溢出,导致一个负整数,最终得到一个错误的休息值。当我看到一些冗长的代码片段(也给出了错误的结果)时,我忍不住要分享我自己的代码。积分转至Finding Modulus of a Very Large Number with a Normal Number

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个位置,因为它小于JavaScript中最大整数的15个(和一些)位置,它导致一个大于97的数字,这是一个很好的整数。前两个论点很重要。

答案 1 :(得分:9)

Benedikt版本的一系列改进:“cRest + =''+ cDivident;”是一个错误修复; parseInt(divisor)可以将两个参数作为字符串传递;最后检查空字符串是否总是返回数值;添加了var语句,因此它不使用全局变量;将foreach转换为旧式,因此它适用于具有较旧Javascript的浏览器;修正了cRest == 0; bug(感谢@ 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 :(得分:5)

看起来你已成为受害者:What is JavaScript's highest integer value that a Number can go to without losing precision?

重申另一个话题中的内容:

  

它们是64位浮点值,最大精确积分值是2 ^ 53。但是,从规格部分[8.5:数字类型]:

     

某些ECMAScript运算符仅处理-2 ^ 31到2 ^ 31-1(包括两者)或0到2 ^ 32-1(包括0和2 ^ 32-1)范围内的整数。这些运算符接受Number类型的任何值,但首先将每个此类值转换为2 ^ 32个整数值之一。请分别参见第0和0节中的ToInt32和ToUint32运算符的描述

但信用到期的信用。吉米在那里得到了接受的答案来做腿部工作(好吧,谷歌搜索)。

答案 3 :(得分: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;
}

答案 4 :(得分:4)

对于那些只想在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;
};

答案 5 :(得分:3)

Silent Matt为Big Integers开发了一个Javascript library 。它也可以解决这个问题。