如何解决浮点数x.999999小数位导致的重量计算精度问题?
解决浮点数精度问题的保留两位小数函数优化
问题背景
- 浮点数精度异常:计算
49.8 - 12.45时,结果为37.34999999999999而非预期的37.35 - 原截断函数处理后,四次减法无法归零:
- 49.8 - 12.45 → 37.34
- 37.34 - 12.45 → 24.89
- 24.89 - 12.45 → 12.44
- 12.44 无法再减12.45
- 逻辑矛盾:
49.8 / 4 = 12.45,理论上四次减法应能归零
原函数代码:
function threeDecimals(num) { const multipliedNum = num * 100; const truncatedNum = Math.trunc(multipliedNum); const num3decimals = truncatedNum / 100; return num3decimals; }
优化方案
需求:当数值第三位小数为9时进位保留两位小数,否则沿用原截断逻辑。
优化后的函数代码
function optimizedRound(num) { // 放大1000倍,便于提取第三位小数 const multipliedBy1000 = num * 1000; const integerPart = Math.trunc(multipliedBy1000); const decimalPart = multipliedBy1000 - integerPart; // 处理浮点数精度误差,近似判断第三位小数是否为9 if (Math.abs(decimalPart - 0.9) < 0.0001) { // 进位:放大100倍后加1再截断 return Math.trunc(num * 100 + 1) / 100; } else { // 原截断逻辑 return Math.trunc(num * 100) / 100; } }
代码说明
- 放大1000倍:将第三位小数转化为可直接判断的数值部分,避免浮点数精度干扰
- 近似匹配判断:由于浮点数存储特性,直接判断
decimalPart === 0.9可能失效,用极小阈值做近似比对 - 进位逻辑:当第三位小数为9时,通过
num*100+1实现进位后再截断,保证两位小数的准确性 - 截断逻辑保留:其他场景沿用原截断方式,避免无意义的进位影响计算逻辑
测试验证
针对问题场景测试:
optimizedRound(49.8 - 12.45)返回37.35- 后续减法流程:
- 37.35 - 12.45 → 24.90
- 24.90 - 12.45 → 12.45
- 12.45 - 12.45 → 0
四次减法后成功归零,符合逻辑预期
内容的提问来源于stack exchange,提问作者Legion
相关产品推荐
相关产品推荐

