JavaScript 中的取模 - 大数

发布于 2024-07-23 18:42:08 字数 197 浏览 7 评论 0原文

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

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

Result: 66

这里有什么问题吗?

问候, 贝内迪克特

I try to calculate with JS' modulo function, but don't get the right result (which should be 1). Here is a hardcoded piece of code.

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

Result: 66

Whats the problem here?

Regards,
Benedikt

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

回梦 2024-07-30 18:42:08

对于 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 的数字,并且这是一个很好的整数。 前两个论点很重要。

For an IBAN calculation form a normal bankaccount number I end up with a very large number contained in a string datatype. From this large number I have to find the rest when divided by 97 -> large number % 97.

As soon as I convert the datatype to an integer I get an overflow resulting in a negative integer and eventually a wrong rest value. As I saw some verbose pieces of code (which also gave wrong outcome), I could not resist to share my own. Credits go to 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.
I use 10 positions here as this is smaller than the 15 (and some) positions of max integer in JavaScript, it results in a number bigger than 97 and it's a nice round number. The first two arguments matter.

葬シ愛 2024-07-30 18:42:08

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

function modulo(divident, divisor) {
  let cDivident = '';
  let cRest = '';

  for (let i in divident) {
    let cChar = divident[i];
    let 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;
}

A bunch of improvements to Benedikt's version: cRest += '' + cDivident; is a bugfix; parseInt(divisor) makes it possible to pass both arguments as strings; check for empty string at the end makes it always return numerical values; added var statements so it's not using global variables; converted foreach to old-style for so it works in browsers with older Javascript; fixed the cRest == 0; bug (thanks @Dan.StackOverflow).

function modulo(divident, divisor) {
  let cDivident = '';
  let cRest = '';

  for (let i in divident) {
    let cChar = divident[i];
    let 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;
}
匿名的好友 2024-07-30 18:42:08

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

这是有效的,因为模在加法、减法和乘法上具有分配性:

  • (a+b)% m = ((a%m)+(b%m))%m
  • (ab)%m = ((a%m)-(b%m))%m
  • (ab)%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;
};

For those who simply want to copy&paste a working (functional) solution in ES6 to check 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;}

You could even write it as a one-liner.

The modulo operation is performed on the array of integers storing the actual number (divident, applied as string to function):

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

This works because Modulo is distributive over addition, substraction and multiplication:

  • (a+b)%m = ((a%m)+(b%m))%m
  • (a-b)%m = ((a%m)-(b%m))%m
  • (ab)%m = ((a%m)(b%m))%m

The IBAN function transpiled to ES5 looks like:

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;
};
蛮可爱 2024-07-30 18:42:08

看起来你已经成为这个的受害者:JavaScript 在不丢失精度的情况下可以达到的最大整数值是多少?

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

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

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

但是应得的功劳。 吉米在那里得到了公认的答案,因为他做了跑腿工作(好吧,谷歌搜索)。

looks like you've fallen victim to this: What is JavaScript's highest integer value that a Number can go to without losing precision?

just to reiterate what's in the other thread:

they are 64-bit floating point values, the largest exact integral value is 2^53. however, from the spec section [8.5: Number Type]:

Some ECMAScript operators deal only with integers in the range −2^31 through 2^31−1, inclusive, or in the range 0 through 2^32−1, inclusive. These operators accept any value of the Number type but first convert each such value to one of 2^32 integer values. See the descriptions of the ToInt32 and ToUint32 operators in sections 0 and 0, respectively

But credit where credit is due. Jimmy got the accepted answer over there for doing the legwork (well, googling).

妖妓 2024-07-30 18:42:08

最后,我的解决方案:

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

Finally, my solution:

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;
}
一曲琵琶半遮面シ 2024-07-30 18:42:08

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

Silent Matt has developed a Javascript library for Big Integers. It could solve this issue too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文