我试图理解为什么模运算不能按预期工作:
我需要验证IBAN,并且算法包括做模数。
根据维基百科: enter link description here
3214282912345698765432161182 mod 97 = 1
根据我的Windows计算器:: 3214282912345698765432161182 mod 97 = 1
但是当我在JS中这样做时我得到65:
var result = 3214282912345698765432161182 % 97;
console.log(result);
// result is 65
为什么我在JS中获得65而不是1?
答案 0 :(得分:4)
您的号码高于(2 ^ 53)-1,因此无法正确表示。
您可以使用功能Number#isSafeInteger
检查使用此号码是否安全
const isSafe = Number.isSafeInteger(3214282912345698765432161182);
console.log(isSafe);
答案 1 :(得分:1)
查看解决您直接问题的其他答案。如果您想自己动手,可以使用以下方法解决实际问题。可能有一个库已经在那里做了,但它有可能使用如下所述的相同方法。
引用您链接到的the very wikipedia page:
任何用于直接计算D mod 97的计算机编程语言或软件包都必须能够处理超过30位的整数。实际上,这只能通过支持任意精度算术或可以处理220位(无符号)整数的软件来完成,这些特性通常不是标准的。如果使用的应用程序软件不能提供处理此大小的整数的能力,则可以以分段方式执行模运算(与UN CEFACT TBG5 Javascript程序的情况一样)。
让我们看看你如何用一个例子来实现这个方法:
D = 3214282912345698765432161182
让我们将这个数字分成四部分:
P1 = 321428291 // first 9 digits
P2 = 2345698 // next 7 digits
P3 = 7654321 // next 7 digits
P4 = 61182 // last 5 digits
然后,根据维基百科D % 97 == 1
,如果以下步骤引导您N % 97 == 1
:
从D(P1)的前9位构造N
N = 321428291
计算N mod 97 = 70
从上面的结果(步骤2)构建一个新的9位数N,接着是 D(P2)的后7位数字。
N = 702345698
从上面的结果(步骤4)构建一个新的9位数N,然后是 D(P3)的下一个7位数。
N = 297654321
从上面的结果(步骤6)构建一个新的N,然后是 D(P4)的剩余5位数
N = 2461182
从步骤8开始,最终结果为D mod 97 = 1且IBAN已通过 这个校验位测试。
这是dfsq提供的类似方法的简单ES6实现:
function checkIBAN(iban) {
const parts = iban.match(/.{1,6}/g);
return parts.reduce((prev, curr) => Number(prev + curr) % 97, '');
}
console.log(checkIBAN("3214282912345698765432161182"));
答案 2 :(得分:0)
JavaScript最高整数值而不会丢失精度
+/- 9007199254740991
数量小于2 ^ 53的数字可以用数字类型表示。
您可以在浏览器控制台中运行 Number.MAX_SAFE_INTEGER 来检查这一点。
如果直接存储,大于此值的整数将失去其精度。
查看此博客文章,了解如何在Javascript中处理BigIntegers。
答案 3 :(得分:0)
此library可以解决您的问题或通过npm安装
npm install big-integer
代码段在节点
中运行var bigInt = require("big-integer");
var largeNumber = bigInt("3214282912345698765432161182");
console.log(largeNumber.divmod(97).remainder.value)
输出为1