19

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

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

Result: 66

这里有什么问题?

问候, 本尼迪克特

4

6 回答 6

14

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

于 2013-04-15T15:51:16.530 回答
12

Benedikt 版本的一系列改进:“cRest += '' + cDivident;” 是一个错误修正;parseInt(divisor) 可以将两个参数作为字符串传递;最后检查空字符串使其始终返回数值;添加了 var 语句,因此它不使用全局变量;将 foreach 转换为旧式 for,因此它可以在使用旧 Javascript 的浏览器中工作;修复了 cRest == 0;错误(感谢@Dan.StackOverflow)。

函数模(除数,除数){
    var cDivident = '';
    var cRest = '';

    for (var i in divident ) {
        var cChar = 分红[i];
        var cOperator = cRest + '' + cDivident + '' + cChar;

        if ( cOperator < parseInt(divisor) ) {
                cDivident += '' + cChar;
        } 别的 {
                cRest = cOperator % 除数;
                如果(cRest == 0){
                    cRest = '';
                }
                cDivident = '';
        }

    }
    cRest += '' + cDivident;
    如果(cRest == ''){
        休息 = 0;
    }
    返回 cRest;
}
于 2010-05-05T10:35:51.700 回答
5

看起来你已经成为这个问题的受害者:JavaScript 的最高整数值是多少,一个 Number 可以达到而不会丢失精度?

只是重申另一个线程中的内容:

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

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

但是信用到期。吉米在那里得到了接受的答案,因为他做了跑腿工作(嗯,谷歌搜索)。

于 2009-05-30T15:23:55.007 回答
5

对于那些只想在 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
  • (ab)%m = ((a%m)-(b%m))%m
  • (a b)%m = ((a%m) (b%m))%m

转译为 ES5 的 IBAN 函数如下所示:

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;
};
于 2017-07-19T11:42:53.620 回答
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;
}
于 2009-06-17T22:29:44.450 回答
3

Silent Matt 为大整数开发了一个 Javascript。它也可以解决这个问题。

于 2010-12-14T21:14:48.460 回答