我尝试用JS的取模函数进行计算,但没有得到正确的结果(应该是1)。这是一段硬编码的代码。
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
这里有什么问题吗?
问候, 本尼迪克特
对于 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 的数字,并且这是一个很好的整数。前两个参数很重要。
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;
}
对于那些只想在 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);
};
这是有效的,因为模对加法、减法和乘法具有分配性:
转换为 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;
};
看起来你已经成为了这个问题的受害者:JavaScript 在不损失精度的情况下可以达到的最高整数值是多少?
只是重申一下其他线程中的内容:
它们是64位浮点值,最大精确积分值为2^53。然而,从规范部分[8.5:数字类型]:
某些 ECMAScript 运算符仅处理 -2^31 到 2^31−1(含)范围内的整数,或 0 到 2^32−1(含)范围内的整数。这些运算符接受 Number 类型的任何值,但首先将每个此类值转换为 2^32 整数值之一。分别参见第 0 节和第 0 节中对 ToInt32 和 ToUint32 运算符的描述
但是应得的功劳。吉米在那里得到了公认的答案,因为他做了跑腿工作(好吧,谷歌搜索)。
最后,我的解决方案:
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;
}
Silent Matt 为大整数开发了一个 Javascript 库 。也可以解决这个问题。