什么是「超大整数」?
JavaScript 采用 IEEE754标准 中的浮点数算法来表示数字 Number。
我也没花时间去详细了解 IEEE754标准 ,但对于处理超大整数,了解下面的几个知识点就足够了。
首先,JavaScript 实际上可以表示的最大数是: 1.7976931348623157e+308
Number.MAX_VALUE; // 1.7976931348623157e+308
虽然这个数可以正确表示出来,但会存在「精度丢失」的问题。
那什么是「精度丢失」? 我们看看下面的例子:
num1 = 10000000000000000000000000 + 11111111111111111111111111; // 2.111111111111111e+25 num2 = 21111111111111111111111000; // 2.111111111111111e+25 num1 === num2; // true
按照常规的数学预算, num1 的计算结果是 21111111111111111111111111,而 num2 的值是 21111111111111111111111000,两者是不可能相等。但实际上 JavaScript 可以精确表示到个位的最大整数是:9007199254740992
Math.pow(2, 53); // 9007199254740992 Math.pow(2, 53) === Math.pow(2, 53) + 1; // true 9007199254740992 === 9007199254740992 + 1; // true
关于 JavaScript Number 的一些上下极限,更详细的资料可以看下图:
正因为 JavaScript 的 Number 类型存在这些限制,当我们需要处理两个「超大整数」的相加时,直接套用加法运算符会存在以下问题:
- 当结果大于 Math.pow(2, 53) 时,会出现精度丢失,导致最终结果存在偏差
- 当结果大于 Number.MAX_VALUE,直接返回 Infinity
为了解决这些问题,才产生了「超大整数」加法的需求,实现代码如下:
var largeIntegerAddition = function () {
function isNumberString() {
var result = true;
for (var i = arguments.length; i--;) {
if (typeof arguments[i] !== "string" !/^\d+$/.test(arguments[i])) {
console.error("arguments format is incorrect!");
result = false;
break;
}
}
return result;
}
function trimHeadZero(numberStr) {
return numberStr.replace(/^0*/, "");
}
return function () {
var bigNum1 = arguments[0],
bigNum2 = arguments[1];
if (!bigNum2) {
return isNumberString(bigNum1) ? trimHeadZero(bigNum1) : "0";
} else {
if (!isNumberString(bigNum1, bigNum2)) {
return "0";
}
bigNum1 = trimHeadZero(bigNum1);
bigNum2 = trimHeadZero(bigNum2);
var carry = 0, // 进位
bigNum1Split = bigNum1.split("").reverse(),
bigNum2Split = bigNum2.split("").reverse(),
result = "",
maxNumSize = bigNum1Split.length > bigNum2Split.length ? bigNum1Split.length : bigNum2Split.length;
for (var i = 0; i < maxNumSize; i++) {
var n1 = bigNum1Split[i] ? +bigNum1Split[i] : 0,
n2 = bigNum2Split[i] ? +bigNum2Split[i] : 0,
sum = (n1 + n2 + carry).toString();
if (sum.length > 1) {
carry = +sum.slice(0, 1);
result = sum.slice(1, 2) + result;
} else {
carry = 0;
result = sum + result;
}
}
if (carry !== 0) {
result = carry + result;
}
if (arguments[2]) {
var argumentArr = Array.prototype.slice.call(arguments, 0).slice(2);
argumentArr.unshift(result);
return largeIntegerAddition.apply(this, argumentArr);
} else {
return result;
}
}
}
}();
测试用例:
// 测试用例
function unitTest(arg, result) {
var res = largeIntegerAddition.apply(this, arg);
console.log(res, res === result);
}
unitTest([], "");
unitTest(["012", 3], "15");
unitTest(["012", "0013", "214", 100002], "100241");
unitTest(["1.1111111111111111e+227", "1"], "1.1111111111111111e+227");
unitTest(["123"], "123");
unitTest(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"], "45");
unitTest(["0", "2", "3", "4", "123"], "132");
unitTest(["012", "3"], "15");
unitTest(["012", "0013", "214", "100002"], "100241");
unitTest(["99999999999999999999", "1"], "100000000000000000000");
unitTest(["99999999999999999999", "11111111111111111111"], "111111111111111111110");
unitTest(["99999999999999999999", "11111111111111111111", "11111111"], "111111111111122222221");
unitTest(["4810284728175829182", "92817475910285750182"], "97627760638461579364");
unitTest(["4810284728175829182", "92817475910285750182", "9728172845"], "97627760648189752209");
unitTest(["4810284728175829182", "92817475910285750182", "9728172845" , "92875018002020102"], "97720635666191772311");
unitTest([
(function () {
var str = "";
for (var i = 500; i--;) {
str += "9";
}
return str;
})(),
(function () {
var str = "";
for (var i = 500; i--;) {
str += "1";
}
return str;
})()
], (function () {
var str = "";
for (var i = 500; i--;) {
str += "1";
}
return str + "0";
})());
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索return
, function
, 整数
, unittest
, result
, 超大数
, arguments
, 高精度加法
, javascript整数
javascript的split
javascript 加法、javascript加法运算、javascript 加减法、javascript date加法、javascript加法计算器,以便于您获取更多的相关知识。