解决JS浮点数精度确实与大数溢出

发布时间:2026/6/24 10:44:57
解决JS浮点数精度确实与大数溢出 import Big from ‘big.js’;import { z } from ‘zod’;// 定义参数校验规则// 兼容数字、合法的数字字符串如 ‘12.34’// 拒绝NaN, Infinity, 纯字母字符串, 对象, 数组等const NumberCoerceSchema z.union([z.number().finite(), // 必须是有限的数字z.string().regex(/^-?\d(.\d)?$/, “无效的数字格式”) // 必须是合法的数字字符串]).transform((val) new Big(val)); // 校验通过后直接转换为 Big 对象/**加法函数param {number|string} a - 加数 A (默认 0)param {number|string} b - 加数 B (默认 0)returns {string} 以字符串形式返回精确结果避免大数失真*/function ultimateSum(a 0, b 0) {try {// 运行时强校验并解析const bigA NumberCoerceSchema.parse(a);const bigB NumberCoerceSchema.parse(b);// 使用 big.js 进行高精度加法return bigA.plus(bigB).toString();} catch (error) {if (error instanceof z.ZodError) {// 结构化抛出异常方便前端输入框或日志捕获具体是哪个参数错了throw new TypeError(参数校验失败: ${JSON.stringify(error.format())});}throw error;}}// 测试用例 // 1. 浮点数高精度测试console.log(ultimateSum(0.1, 0.2)); // “0.3” (完美)console.log(ultimateSum(0.111, 0.222)); // “0.333”// 2. 字符串与数字混用console.log(ultimateSum(‘1.5’, 2.5)); // “4”// 3. 缺省值测试console.log(ultimateSum(5)); // “5”console.log(ultimateSum()); // “0”// 4. 超大数字测试超过 JS 安全整数限制console.log(ultimateSum(‘9007199254740991’, 1)); // “9007199254740992”// 错误拦截测试 (均会抛出语义明确的错误) // ultimateSum(1, NaN); // 报错: 参数校验失败 (finite 校验不通过)// ultimateSum(1, ‘abc’); // 报错: 参数校验失败 (regex 校验不通过)// ultimateSum(1, {}); // 报错: 参数校验失败 (类型不匹配)