怎样用JavaScript实现大数运算?

来源:IPIPP.com作者:头衔:全栈工程师
导读:本期聚焦于小伙伴创作的《怎样用JavaScript实现大数运算?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《怎样用JavaScript实现大数运算?》有用,将其分享出去将是对创作者最好的鼓励。

JavaScript原生Number类型的安全整数范围是-(2^53-1)到2^53-1,超出这个范围的整数运算会出现精度丢失,比如直接执行9999999999999999 + 1可能得到不符合预期的结果。因此处理大数运算时,通常将数字转为字符串,模拟人工计算的过程逐位处理,避免精度问题。

怎样用JavaScript实现大数运算?

大数运算的核心思路

大数运算的本质是模拟我们手动列竖式计算的过程,核心处理点包括:

  • 将数字转为字符串,从最低位(字符串末尾)开始逐位处理
  • 处理进位、借位逻辑,对应不同运算的规则
  • 处理前导零,避免结果出现多余的零开头
  • 处理正负号,分情况处理同号、异号的运算逻辑

大数加法实现

大数加法的逻辑和手动加法一致,从末位开始相加,满十进一,最后反转结果并去除前导零。

function bigNumberAdd(a, b) {
    // 处理输入为数字的情况,转为字符串
    a = String(a);
    b = String(b);
    let i = a.length - 1;
    let j = b.length - 1;
    let carry = 0; // 进位值
    let result = [];

    // 从最低位开始逐位相加
    while (i >= 0 || j >= 0 || carry > 0) {
        const numA = i >= 0 ? parseInt(a[i]) : 0;
        const numB = j >= 0 ? parseInt(b[j]) : 0;
        const sum = numA + numB + carry;
        result.push(sum % 10);
        carry = Math.floor(sum / 10);
        i--;
        j--;
    }

    // 反转结果并转为字符串,去除前导零
    let res = result.reverse().join('');
    res = res.replace(/^0+/, '') || '0';
    return res;
}

// 测试示例
console.log(bigNumberAdd('9999999999999999', '1')); // 输出10000000000000000
console.log(bigNumberAdd('123456789', '987654321')); // 输出1111111110

大数减法实现

大数减法需要先判断两个数的大小,用大的减小的,再根据原始符号调整结果的正负,处理借位逻辑。

function bigNumberSubtract(a, b) {
    a = String(a);
    b = String(b);
    // 判断a是否大于等于b,用于确定结果正负
    const isANotSmaller = (a, b) => {
        if (a.length !== b.length) return a.length > b.length;
        return a >= b;
    };

    let isNegative = false;
    if (!isANotSmaller(a, b)) {
        // 交换a和b,标记结果为负
        [a, b] = [b, a];
        isNegative = true;
    }

    let i = a.length - 1;
    let j = b.length - 1;
    let borrow = 0; // 借位值
    let result = [];

    while (i >= 0 || j >= 0) {
        const numA = i >= 0 ? parseInt(a[i]) : 0;
        const numB = j >= 0 ? parseInt(b[j]) : 0;
        let diff = numA - borrow - numB;
        if (diff < 0) {
            diff += 10;
            borrow = 1;
        } else {
            borrow = 0;
        }
        result.push(diff);
        i--;
        j--;
    }

    // 反转结果,去除前导零
    let res = result.reverse().join('').replace(/^0+/, '') || '0';
    return isNegative ? '-' + res : res;
}

// 测试示例
console.log(bigNumberSubtract('10000000000000000', '9999999999999999')); // 输出1
console.log(bigNumberSubtract('123456', '654321')); // 输出-530865

大数乘法实现

大数乘法模拟竖式乘法,用一个数的每一位去乘另一个数的每一位,结果按位置累加,最后处理进位。

function bigNumberMultiply(a, b) {
    a = String(a);
    b = String(b);
    const lenA = a.length;
    const lenB = b.length;
    // 结果最多有lenA + lenB位,初始化全0数组
    const result = new Array(lenA + lenB).fill(0);

    // 从最低位开始逐位相乘
    for (let i = lenA - 1; i >= 0; i--) {
        for (let j = lenB - 1; j >= 0; j--) {
            const product = parseInt(a[i]) * parseInt(b[j]);
            // 乘积放在对应位置,位置是i+j+1
            const pos = i + j + 1;
            const sum = product + result[pos];
            result[pos] = sum % 10;
            result[pos - 1] += Math.floor(sum / 10);
        }
    }

    // 去除前导零,转为字符串
    let res = result.join('').replace(/^0+/, '') || '0';
    return res;
}

// 测试示例
console.log(bigNumberMultiply('123456', '654321')); // 输出80779853376
console.log(bigNumberMultiply('9999', '9999')); // 输出99980001

大数除法实现

大数除法采用试商法,模拟手动除法的过程,逐位取被除数,计算当前位能商几,更新余数继续计算。

function bigNumberDivide(dividend, divisor) {
    dividend = String(dividend);
    divisor = String(divisor);
    if (divisor === '0') throw new Error('除数不能为0');
    if (dividend === '0') return '0';

    let result = [];
    let remainder = ''; // 当前余数

    for (let i = 0; i < dividend.length; i++) {
        // 拼接当前位的数字到余数
        remainder += dividend[i];
        remainder = remainder.replace(/^0+/, '') || '0';

        // 试商,从9到0找最大的能乘的数不超过余数
        let count = 0;
        while (bigNumberSubtract(remainder, bigNumberMultiply(divisor, count)) >= 0) {
            count++;
        }
        count--; // 上一个满足条件的数
        result.push(count > 0 ? count : 0);
        // 更新余数
        remainder = bigNumberSubtract(remainder, bigNumberMultiply(divisor, count));
    }

    // 去除结果前导零
    let res = result.join('').replace(/^0+/, '') || '0';
    return res;
}

// 测试示例
console.log(bigNumberDivide('80779853376', '654321')); // 输出123456
console.log(bigNumberDivide('10000000000000000', '9999999999999999')); // 输出1

实现注意事项

以上实现是基础的字符串大数运算逻辑,实际使用中还可以做更多优化:

  • 可以支持正负号处理,在加减法里扩展符号逻辑
  • 乘法可以优化为更高效的算法,比如Karatsuba算法提升大位数相乘的性能
  • 除法可以优化试商逻辑,避免重复调用乘法和减法,提升计算效率
  • 如果涉及小数运算,需要额外处理小数点的位置,统一转为整数计算后再调整小数点

如果需要生产环境使用,也可以直接使用成熟的大数库,比如BigInt(ES2020引入的原生大整数类型),或者第三方库如bignumber.js,这些库已经处理了各种边界情况,可靠性更高。

下面是使用BigInt实现大数运算的示例,原生BigInt可以直接处理大整数,不需要手动实现运算逻辑:

// BigInt类型的大数运算,需要在数字后加n标识
const a = 9999999999999999n;
const b = 1n;
console.log(a + b); // 输出10000000000000000n
console.log(a * b); // 输出9999999999999999n
// 注意BigInt和Number不能直接混合运算,需要统一类型

JavaScript大数运算字符串处理进制转换高精度计算修改时间:2026-05-29 22:42:07

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。