新闻详情

新闻详情

首页 / 资讯中心 / 详情

搞懂世界上最大的数:从BigNumber源码看大数运算最佳实践

发布时间:2026/11/13 1:48:41来源:尧图网络
搞懂世界上最大的数:从BigNumber源码看大数运算最佳实践
搞懂世界上最大的数:从BigNumber源码看大数运算最佳实践 很多工程师在面试或实战中,一提到世界上最大的数就头大。你会写 1+1,但让你处理 1000 位精度的金融数据或密码学哈希,代码直接崩盘。这不是语法问题,是最佳实践缺失。 你卡在“学会语法却不知怎么搭项目”的瓶颈上。知道 Number.MAX_VALUE 是 \(1.8 \times 10^{308}\),但不知道如何在业务中安全地表示更大的数。今天拆解 bignumber.js 核心源码,看透大数运算的底层逻辑,解决你在大数处理上的工程难题。 入口定位:为什么原生 JS 不够用 在 JavaScript 中,所有数字默认是 IEEE 754 双精度浮点数。这意味着有效数字只有 53 位二进制,换算成十进制大约 15-17 位。一旦超过这个精度,后面的数字会被截断或变成近似值。 // 经典坑:浮点数精度丢失 console.log(0.1 + 0.2); // 0.30000000000000004// 超过 MAX_SAFE_INTEGER console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 console.log(Number.MAX_SAFE_INTEGER + 1); // 9007199254740992 (错误! 变成了偶数)当业务涉及世界上最大的数概念,比如区块链交易 ID、高精度科学计算,原生 Number 类型彻底失效。我们需要引入任意精度算术库。bignumber.js 是 Node.js 生态中轻量级且性能优异的解决方案。它的入口很简单,但核心实现却充满了工程智慧。 核心片段:BigNumber 构造函数与字符串解析 bignumber.js 的核心类是 BigNumber。它的构造函数接收一个数字、字符串或另一个 BigNumber 实例。关键在于,它如何解析输入并存储内部状态。 我们来看 src/bignumber.js 中的关键部分(简化版,保留核心逻辑): // 语言: JavaScript // 文件: bignumber.js 核心构造逻辑片段function BigNumber(v) {var x = this;var isBigNum = v instanceof BigNumber;// 1. 验证输入类型,防止非法值污染状态if (typeof v === 'number' v * 0 !== 0) {throw new TypeError('Invalid number: ' + v);}// 2. 如果是 BigNumber 实例,直接复制内部状态 (性能优化)if (isBigNum) {x.s = v.s; // 符号: 1 正, -1 负, 0 零x.e = v.e; // 指数: 科学计数法的指数部分x.c = v.c.slice(); // 系数: 数组形式存储的各位数字,避免引用共享return x;}// 3. 处理字符串输入,正则提取符号、系数、指数if (typeof v === 'string') {v = v.trim();var match = v.match(/^-?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i);if (!match) throw new TypeError('Invalid string: ' + v);x.s = v.charAt(0) === '-' ? -1 : 1;var numStr = v.replace(/^-?|e[+-]?\d+$/i, '');var expStr = v.match(/e([+-]?\d+)/i);// 解析系数:去掉小数点,计算指数偏移var dotIndex = numStr.indexOf('.');var coeffStr = numStr.replace('.', '');x.c = coeffStr.split('').map(Number);// 计算指数: 原始指数 + 小数点移动位数var exp = expStr ? parseInt(expStr[1], 10) : 0;if (dotIndex !== -1) {exp -= (coeffStr.length - (dotIndex + 1));}x.e = exp;// 4. 标准化:去除前导零和末尾零normalize(x);} }逐行解读:类型安全:v * 0 !== 0 巧妙排除了 NaN 和 Infinity。 浅拷贝陷阱:v.c.slice() 至关重要。如果直接赋值 x.c = v.c,两个 BigNumber 实例会共享同一个数组,修改一个会导致另一个数据污染。这是源码中最容易踩的坑。 字符串解析:正则 /^-?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i 覆盖了整数、小数、科学计数法。 指数计算:exp -= (coeffStr.length - (dotIndex + 1)) 这行代码是核心。例如 123.45,系数是 12345,小数点后有 2 位,所以指数要减 2,变成 12345 * 10^-2。 标准化:normalize 函数确保内部存储的唯一性,比如 001.230 会变成 1.23。设计思想:数组存储与基数优化 为什么用数组 c 存储系数,而不是一个巨大的数字?因为 JS 的 Number 精度有限。用数组存储每一位数字,可以无限扩展精度。 但这里有个最佳实践:bignumber.js 默认使用 1e14 作为基数(Base),而不是 10。 // 语言: JavaScript // 内部存储示例: 数字 12345678901234567890// 如果 Base = 10: // c: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0] // e: 19// 如果 Base = 1e14 (100000000000000): // c: [12345678901234, 567890] // 每个元素最大不超过 99999999999999 // e: 19 - 13 = 6 (因为第一组占了14位,但这里需要仔细对齐) // 实际逻辑: c[0] * BASE^1 + c[1] * BASE^0设计优势:减少数组长度:20 位的数字,Base=10 需要 20 个元素,Base=1e14 只需要 2 个。内存占用降低,循环遍历次数减少。 乘法效率:大数乘法是 O(n*m) 复杂度。元素越少,乘加操作次数越少。在 CSDN 的一篇深度解析文章中提到,对于 1000 位数字的乘法,Base=1e14 比 Base=10 快约 4 倍。 进位处理:虽然基数变大,进位时可能需要处理更大的中间值,但现代 CPU 处理 64 位整数非常快,JS 引擎对整数运算有优化,所以整体收益大于成本。手写简化版:加法与进位逻辑 理解设计思想后,我们手写一个极简版的大数加法,聚焦于进位逻辑。这是大数运算的灵魂。 // 语言: JavaScript // 简化版 BigNumber 加法实现class SimpleBigNum {constructor(str) {// 简化:只处理正整数,不含小数点this.digits = str.split('').reverse().map(Number); // 低位在前this.sign = 1;}add(other) {let a = this.digits;let b = other.digits;let result = [];let carry = 0;let maxLen = Math.max(a.length, b.length);for (let i = 0; i maxLen; i++) {let sum = (a[i] || 0) + (b[i] || 0) + carry;// 核心:Base=10 的进位逻辑// 如果 sum = 10,当前位取 sum % 10,进位 1result.push(sum % 10);carry = Math.floor(sum / 10);}// 处理最终进位if (carry 0) {result.push(carry);}// 反转回高位在前,并转换为字符串return new SimpleBigNum(result.reverse().join(''));}toString() {return this.digits.reverse().join('');} }// 测试 const num1 = new SimpleBigNum('99999999999999999999'); const num2 = new SimpleBigNum('1'); console.log(num1.add(num2).toString()); // 100000000000000000000避坑指南:低位在前:存储时反转数组,因为加法从最低位开始。如果高位在前,需要复杂的索引计算。 边界检查:a[i] || 0 处理长度不一致的情况。 最终进位:循环结束后,carry 可能不为 0,必须单独 push。 性能瓶颈:这个手写版只适用于 Base=10。实际工程中,必须使用 Base=1e14 或更高,否则处理 1000 位数时,数组操作开销巨大。应用场景:金融与区块链中的大数 金融领域:高精度计算是刚需。银行利息计算、股票交易价格,误差不能超过 0.0001。使用 bignumber.js 可以避免浮点数误差。 const BigNumber = require('bignumber.js'); const price = new BigNumber('123456789.123456789'); const quantity = new BigNumber('1000'); const total = price.times(quantity); console.log(total.toString()); // 123456789123.456789区块链领域:以太坊使用 256 位整数。交易 Gas Fee 计算、地址哈希,都涉及超过 64 位的大数。bignumber.js 虽然轻量,但对于超高频交易场景,可能需要更专业的库如 bn.js,其内部使用 Base=2^26 优化位运算。 避坑:不要混合类型:始终用字符串初始化 BigNumber,避免 new BigNumber(0.1) 带来的精度丢失。 比较陷阱:a b 是 JS 原生比较,会转成浮点数。必须用 a.gt(b)。 序列化:JSON.stringify 不支持 BigNumber。自定义 toJSON 方法,返回字符串。结尾互动 大数运算不是玄学,是工程问题。世界上最大的数在计算机里只是一串数组,关键看你怎么存、怎么算。 你在项目中遇到过哪些大数处理的坑?是金融对账差一分,还是区块链 Gas 费算错?评论区留言,挨个回。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/13 0:43:49

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/12 23:59:09

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/12 9:50:02

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/12 9:25:38

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/12 15:57:44

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/13 0:02:27

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉