🔢前端解决浮点数运算精度丢失的问题

场景复现

js 复制代码
const value1 = 15966.2 + 3103.3 + 1562.9 + 933.9
console.log('👉 ~ value1:', value1)

上面的这些数值相加的结果应该是21566.3

但是在浏览器中运算的时候,结果却变成了21566.300000000003

那么为什么会这样呢?

这是因为 JavaScript 内部的数字均以 IEEE 754 标准的双精度浮点数格式存储,这种格式只能精确表示有限个小数,而对于一些无限循环小数或无理数,无法精确表示,就会出现精度丢失的情况。

有一些前端的面试题就会问你 为什么0.1+0.2的结果不等于0.3

总之, 前端计算存在这么一个问题。

几种解决方案对比

转化为整数计算

js 复制代码
function addDecimals(num1, num2) {
    const multiplier = Math.pow(
      10,
      Math.max(
        num1.toString().split('.')[1]?.length || 0,
        num2.toString().split('.')[1]?.length || 0
      )
    )
    return (
      (Math.round(num1 * multiplier) + Math.round(num2 * multiplier)) /
      multiplier
    )
}
console.log(addDecimals(0.1, 0.2)) // 0.3
console.log(addDecimals(0.15, 0.15)) // 0.3

这种方只适合小数量计算,大数还是不行

用toFixed()格式化

这种方式没有什么意义,只能展示的时候用,并且也没有解决这个问题

位数放大之后会发现还是有问题

字符串模拟运算

这种方式是目前最为靠谱的一种方式,从源头上解决了这个问题。

很多处理浮点数相关的第三方库实现原理都是基于这种方式来实现的

第三方库

  • Math.js:一个用于 JavaScript 和 Node.js 的扩展数学库

  • decimal.js: 计算任意精度的十进制类型。

  • big.js:一个小型,快速,易于使用的库,用于任意精度的十进制算术运算。

  • bignumber.js: 一个用于任意精度算术的 JavaScript 库。

这些第三方库都可以解决这个问题

bignumber.js的使用

这边我以这个库为例来解决这个问题,这个库的解决原理就是前面提到的字符串模拟运算。

安装

用包管理器安装

shell 复制代码
npm install bignumber.js

或者直接下载bignumber.js文件,通过script引入

github地址:MikeMcl/bignumber.js: 一个用于任意精度小数和非小数运算的 JavaScript 库 --- MikeMcl/bignumber.js: A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic

cdn地址:cdn.jsdelivr.net/npm/bignumb...

相加

js 复制代码
let sum = new BigNumber(0)
const numbers = [15966.2, 3103.3, 1562.9, 933.9]
numbers.forEach((value) => (sum = sum.plus(value)))
console.log('👉 ~ numbers:', sum.toString())

结果如下:

相减

js 复制代码
const numbers = [15966.2, 3103.3, 1562.9, 933.9]
const value1 = new BigNumber(15966.2)
console.log('👉 ~ value1:', value1.minus(1.1231).toString())

结果如下:

相乘

js 复制代码
const value1 = new BigNumber(15966.2)
console.log('👉 ~ value1:', value1.multipliedBy(21).toString())

结果如下:

相除

js 复制代码
const value1 = new BigNumber(15966.2)
console.log('👉 ~ value1:', value1.div(21).toString())

结果如下:

判断是否相等和比较大小

js 复制代码
const value1 = new BigNumber(15966.2)
const value2 = new BigNumber(15966.3)
const value3 = new BigNumber(15966.2)
const value4 = new BigNumber(15966.1)
console.log('15966.2 -> 15966.3 ', value1.comparedTo(value2))
console.log('15966.2 -> 15966.2 ', value1.comparedTo(value3))
console.log('15966.2 -> 15966.1 ', value1.comparedTo(value4))

结果如下:

  • -1: 小于
  • 0: 相等
  • 1: 大于

结尾

像这种涉及到精度计算的,开发中最好都是直接用第三方库去处理,避免出现计算错误之类的问题,导致背大锅。

相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax