JavaScript:不使用BigInt()及工具库实现string转BigInt与字符串算术
不依赖BigInt()和算术库的大整数字符串处理方案
关于typeof运算符的使用
typeof是JavaScript原生的类型检测运算符,不属于BigInt构造函数或第三方算术工具库,完全可以合法使用,比如用来验证输入是否为有效字符串、检查中间变量类型等。
字符串转大整数内部表示(替代BigInt())
由于直接将超长数字字符串转为Number会丢失精度,我们需要用数组模拟大整数存储,推荐采用倒序存储每一位数字的方式,这样更方便处理算术运算中的进位/借位:
function strToDigitArray(numStr) { const digitArr = []; // 从字符串末尾向前遍历,将每个字符转为数字存入数组 for (let i = numStr.length - 1; i >= 0; i--) { // 利用字符编码转数字,避免额外依赖 digitArr.push(numStr.charCodeAt(i) - 48); // '0'的ASCII编码为48 } return digitArr; }
这个函数将"12345"转为[5,4,3,2,1],低位在前,后续运算时从数组头部开始处理,进位直接向后追加即可。
字符串算术操作核心提示
所有运算都基于逐位处理逻辑,手动实现进位、借位,以下是核心操作的思路:
1. 加法
- 遍历两个数字数组的每一位,逐位相加并加上进位
- 每一位的结果取模10得到当前位数字,判断是否产生进位(和≥10则进位为1,否则为0)
- 遍历结束后若仍有进位,追加到结果数组末尾
- 最后将结果数组倒转并拼接为字符串
示例代码:
function addBigNums(aStr, bStr) { const a = strToDigitArray(aStr); const b = strToDigitArray(bStr); const result = []; let carry = 0; // 手动比较长度,完全规避Math库依赖 const maxLen = a.length > b.length ? a.length : b.length; for (let i = 0; i < maxLen || carry; i++) { const digitA = a[i] ?? 0; const digitB = b[i] ?? 0; const sum = digitA + digitB + carry; result.push(sum % 10); carry = sum >= 10 ? 1 : 0; } // 倒转数组并转为字符串 return result.reverse().join(''); }
2. 减法
- 先比较两个数字字符串的大小:长度更长的数更大;长度相同则逐位从左到右比较
- 确定被减数和减数后,逐位相减,若当前位被减数小于减数则向前一位借位(借1当10)
- 最后去除结果字符串前的冗余零(注意结果不能是空字符串,至少保留"0")
3. 乘法
- 采用小学乘法思路:用第一个数的每一位乘第二个数的每一位,结果存入对应索引(i+j)的位置
- 遍历完成后处理每一位的进位(每一位的值除以10得到进位,取模10得到当前位)
- 最后倒转数组并转为字符串
4. 除法
- 采用试商法:从被除数的高位开始,逐位取出组成临时数,尝试除以除数得到商的每一位
- 记录每次的余数,用于下一位的计算
- 最后处理商的前导零,余数保留为字符串
优化建议
- 可以将数字按每4位一组拆分存储(比如
"12345678"转为[5678, 1234]),减少循环次数,提升运算效率,此时进位按10000处理 - 提前实现数字字符串的合法性校验(比如排除非数字字符、空字符串等)
内容的提问来源于stack exchange,提问作者Chaplinskyi Artyom
相关产品推荐
相关产品推荐

