JavaScript超大整数加法
什么是「超大整数」?
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); //
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';
})());
本文作者:Maple Jan
本文链接:http://www.cnblogs.com/maplejan/p/3893545.html
JavaScript超大整数加法的更多相关文章
- AC日记——大整数加法 openjudge 1.6 10
10:大整数加法 总时间限制: 1000ms 内存限制: 65536kB 描述 求两个不超过200位的非负整数的和. 输入 有两行,每行是一个不超过200位的非负整数,可能有多余的前导0. 输出 ...
- javascript获取整数随机数
javascript获取整数随机数 // 从4到10的随机数,|0是生成正整数 var numBars = Math.random()*6+4|0; 也可以通过右移0位(或者左移0位)进行取整 var ...
- HDU1002——大整数加法
题目: I have a very simple problem for you. Given two integers A and B, your job is to calculate the S ...
- 2981:大整数加法-poj
2981:大整数加法 总时间限制: 1000ms 内存限制: 65536kB 描述 求两个不超过200位的非负整数的和. 输入 有两行,每行是一个不超过200位的非负整数,可能有多余的前导0. 输 ...
- RNN入门(4)利用LSTM实现整数加法运算
本文将介绍LSTM模型在实现整数加法方面的应用. 我们以0-255之间的整数加法为例,生成的结果在0到510之间.为了能利用深度学习模型模拟整数的加法运算,我们需要将输入的两个加数和输出的结果 ...
- POJ 2506 Tiling(递推+大整数加法)
http://poj.org/problem?id=2506 题意: 思路:递推.a[i]=a[i-1]+2*a[i-2]. 计算的时候是大整数加法.错了好久,忘记考虑1了...晕倒. #includ ...
- openjudge计算概论-大整数加法
/*=====================================================================1004:大整数加法总时间限制: 1000ms 内存限制: ...
- A——大整数加法(HDU1002)
题目: I have a very simple problem for you. Given two integers A and B, your job is to calculate the S ...
- 剑指offer第12题打印从1到n位数以及大整数加法乘法
字符和数字加减就是字符的ASCII码和数字直接加减. 方法一: 1)在字符串操作中给一个整形数字加(字符0)就是把它转化为字符,当然给一个字符减去(字符0)就可以把它转化为数字了:如果确实是最后 ...
随机推荐
- 【DP专辑】ACM动态规划总结
转载请注明出处,谢谢. http://blog.csdn.net/cc_again?viewmode=list ---------- Accagain 2014年5月15日 ...
- java中float/double浮点数的计算失精度问题(转)
如果我们编译运行下面这个程序会看到什么? public class Test { public static void main(String args[]) { ...
- 采取Volley,实现瀑布流
今天停止php,在研究Volley框架的源代码,实现了瀑布流的效果. 为了实现最终的级联效应,一些需要掌握的知识: (1)自己定义布局,由于我们要监听滑究竟部的事件就要实现自己定义的ScrollVie ...
- MEF初体验之七:Using Catalogs
MEF特性化编程模型的价值主张之一是通过catalogs动态发现部件的能力.Catalogs允许应用程序很容易地消费那些通过[Export]已经自我注册的exports. Assembly Catal ...
- hibernate在地图的方法之一协会
[Hibernate]之关于多对一单向关联映射 在项目的开发中多对一的单向关联映射是最常见的关联映射! 这个着重具体解说一下! 比如,我们如今一个组(Group)和人(Person) id name ...
- WPF学习(12)动画
本篇来学习WPF的动画.什么是动画?动画就是一系列帧.在WPF中,动画就是在一段时间内修改依赖属性值的行为,它是基于时间线Timeline的.有人会说,要动画干嘛,华而不实,而且添加了额外的资源消耗而 ...
- poj3671Dining Cows(DP)
主题链接: 啊哈哈,点我点我 题意: 给一个仅仅含有1.2的序列,如何变换n次使序列成为一个非递减的序列,而且使n最小. 思路: 这道题的数据范围是50000,则肯定承受不了n方的复杂度.所以 仅仅能 ...
- SharePoint 2013 配置启用搜索服务
原文:SharePoint 2013 配置启用搜索服务 1.安装完毕SharePoint 2013,新建网站集,点击搜索,出现如下错误(因为没配置,别激动). 2.尝试启动服务器场中的服务之Share ...
- Device "/dev/sdg" is not a partition【再续】
之前创建asm磁盘的时候总结过一下错误:http://blog.csdn.net/rhys_oracle/article/details/17029333 当今天情况是这种.例如以下: 在使用open ...
- TDD和BDD
开发人员看测试之TDD和BDD 前言: 已经数月没有来园子了,写博客贵在坚持,一旦松懈了,断掉了,就很难再拾起来.但是每每看到自己博客里的博文的浏览量每天都在增加,都在无形当中给了我继续写博客的动 ...