如何在JavaScript中比较以字符串表示的大十进制数?
原生JS/TS实现大十进制数比较(无需依赖库)
需求说明
需要实现函数getValuesGreaterThan(num: string | number, values: string[]),从字符串形式的大十进制数数组中筛选出大于指定数值的元素,要求完全避免精度丢失和类型转换异常。这些数值可能超出JavaScript Number类型的精度范围(比如整数部分超过2^53-1,或小数部分过长)。
实现思路
因为仅需比较大小,我们可以通过统一整数化的方式规避精度问题:
- 拆分每个数字的整数部分与小数部分,统一为带小数点的标准格式
- 统计所有待比较数字中最长的小数位数,将所有数字的小数部分补零至该长度,把十进制数转化为无小数的整数字符串
- 借助
BigInt类型转换整数字符串,直接进行大小比较(BigInt支持任意精度的整数运算,无精度丢失问题)
代码实现
function getValuesGreaterThan(num: string | number, values: string[]): string[] { // 将输入转为标准十进制字符串,处理整数、小数、科学计数法格式 const normalizeNum = (n: string | number): string => { let str = typeof n === 'number' ? n.toString() : n.trim(); // 处理科学计数法(如"1e+5"转为"100000") if (/e/i.test(str)) { const [coeff, expStr] = str.split(/e/i); const exp = parseInt(expStr, 10); const [intPart, fracPart = ''] = coeff.split('.'); let newStr = intPart + fracPart; if (exp > 0) { newStr += '0'.repeat(Math.max(0, exp - fracPart.length)); } else if (exp < 0) { newStr = '0.' + '0'.repeat(-exp - intPart.length) + newStr; } return newStr; } // 统一为带小数点的格式,方便后续拆分 return str.includes('.') ? str : `${str}.`; }; const targetStr = normalizeNum(num); // 收集所有待处理字符串,计算最长小数位数 const allStrs = [targetStr, ...values].map(normalizeNum); const maxFracLength = Math.max(...allStrs.map(s => s.split('.')[1].length)); // 将标准化后的字符串转为BigInt const toBigInt = (s: string): BigInt => { const [intPart, fracPart] = s.split('.'); const paddedFrac = fracPart.padEnd(maxFracLength, '0'); return BigInt(intPart + paddedFrac); }; const targetBigInt = toBigInt(targetStr); // 筛选出大于目标值的元素 return values.filter(val => { const valStr = normalizeNum(val); return toBigInt(valStr) > targetBigInt; }); } // 测试示例 const testValues = [ "1643764147.7500000000", "1643764147.7600000000382333388888", "1643764147.7700000000", "9999999999999999999999999999.12345678901234567890" ]; console.log(getValuesGreaterThan("1643764147.76", testValues)); // 输出: ["1643764147.7600000000382333388888", "1643764147.7700000000"]
边界情况说明
- 负数处理:若需支持负数,可先判断符号:负数小于正数;同符号时,用上述方法比较绝对值大小即可。
- 纯整数字符串:如
"123"会被自动转为"123.",补零后正常处理。 - 科学计数法输入:代码已兼容
"1.23e+5"这类格式,会转换为标准十进制字符串后再处理。
内容的提问来源于stack exchange,提问作者Daniel Kaplan
相关产品推荐
相关产品推荐

