【JavaScript】JavaScript实现大数相乘
在 JavaScript 中处理大数相乘时,由于 Number 类型存在精度限制(最大安全整数为 2⁵³-1),需要特殊处理。
一、原生字符串模拟法(兼容性最佳)
通过字符串逐位计算模拟竖式乘法,支持任意位数整数相乘:
function multiplyBigNumbers(num1, num2) {if (num1 === '0' || num2 === '0') return '0';const len1 = num1.length, len2 = num2.length;const pos = new Array(len1 + len2).fill(0); // 存储中间结果的数组// 双重循环实现逐位相乘for (let i = len1 - 1; i >= 0; i--) {const n1 = +num1[i];for (let j = len2 - 1; j >= 0; j--) {const n2 = +num2[j];const sum = pos[i + j + 1] + n1 * n2;pos[i + j + 1] = sum % 10; // 当前位存储个位pos[i + j] += Math.floor(sum / 10); // 进位累加到高位}}// 处理前导零return pos.join('').replace(/^0+/, '') || '0';
}console.log(multiplyBigNumbers('123456789', '987654321'));
// 输出:"121932631112635269"
关键点解释:
- 数组初始化:用
len1 + len2
长度的数组存储中间结果(两数相乘最大位数为两数位数之和) - 进位处理:通过
Math.floor(sum / 10)
计算进位,累加到高位位置 - 前导零处理:使用正则表达式去除结果中无效的前导零
二、BigInt 原生支持(ES11+ 环境)
对于支持 ES11 的环境,可直接使用 BigInt
类型处理大整数运算:
const bigMultiply = (a, b) => {try {return (BigInt(a) * BigInt(b)).toString();} catch {throw new Error('输入必须为整数字符串');}
};console.log(bigMultiply('9007199254740993', '2'));
// 输出:"18014398509481986"
注意事项:
• 仅支持整数运算,无法处理小数
• 数字必须以字符串形式传入,避免直接使用超出安全范围的数值字面量
• 与普通 Number
类型运算需显式转换:BigInt(5) * 2n
(后缀 n
表示 BigInt)
三、第三方库方案(高精度浮点/复杂运算)
对于需要处理浮点数或复杂数学运算的场景,推荐使用 bignumber.js:
import BigNumber from 'bignumber.js';const preciseMultiply = (a, b) => {return new BigNumber(a).multipliedBy(new BigNumber(b)).toString();
};console.log(preciseMultiply('0.2', '0.1')); // "0.02"(避免浮点精度问题)
console.log(preciseMultiply('1e+500', '2e+300')); // "2e+800"
优势:
• 支持科学计数法、小数、指数运算
• 提供链式 API(.plus()
、.minus()
等)
• 精确控制舍入规则和精度
四、性能优化对比
方法 | 时间复杂度 | 适用场景 | 优化建议 |
---|---|---|---|
字符串模拟法 | O(n²) | 兼容性要求高、无第三方依赖 | 使用 Uint8Array 替代普通数组 |
BigInt | O(1) | 现代浏览器、Node.js 环境 | 避免频繁类型转换 |
bignumber.js | O(n log n) | 复杂数学运算、金融计算 | 启用 EXPONENTIAL_AT 配置优化显示 |
五、方案选型指南
- 简单整数运算 → 优先使用
BigInt
(性能最佳) - 旧浏览器兼容 → 字符串模拟法(需自行处理边界条件)
- 科学计算/财务系统 → 第三方库(支持高精度浮点运算)
扩展阅读:对于超大规模运算(如万位级乘法),可结合 WebAssembly 实现性能突破,例如使用 GNU 多精度算术库(GMP)编译为 WASM 模块。