JavaScript解决浮点数运算精度丢失问题的几种方案

 更新时间:2025年06月10日 09:37:23   作者:飞天猫猫头  
在开发项目的过程中,我们难免会遇到数值计算的场景,此时,我们通常会遇到数值计算结果和我们的预期不一致的情况,通常发生这种情况的原因都是因为JavaScript精度丢失的问题,所以本文给大家介绍了JavaScript解决浮点数运算精度丢失问题的几种方案

场景复现

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

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

几种解决方案对比

转化为整数计算

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的使用

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

安装

用包管理器安装

npm install bignumber.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())

结果如下:

相减

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

结果如下:

相乘

const value1 = new BigNumber(15966.2)
console.log('👉 ~ value1:', value1.multipliedBy(21).toString())

结果如下:

相除

const value1 = new BigNumber(15966.2)
console.log('👉 ~ value1:', value1.div(21).toString())

结果如下:

判断是否相等和比较大小

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: 大于

结尾

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

到此这篇关于JavaScript解决浮点数运算精度丢失问题的几种方案的文章就介绍到这了,更多相关JavaScript浮点数运算精度丢失内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript中valueOf函数与toString方法深入理解

    JavaScript中valueOf函数与toString方法深入理解

    基本上,所有JS数据类型都拥有valueOf和toString这两个方法,null除外。它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下
    2012-12-12
  • EL表达式截取字符串的函数说明

    EL表达式截取字符串的函数说明

    这篇文章主要介绍了EL表达式截取字符串的函数说明,在文章下面给大家介绍了JSTL中自带的方法列表以及其描述,需要的朋友参考下吧
    2017-09-09
  • JS实现匀速与减速缓慢运动的动画效果封装示例

    JS实现匀速与减速缓慢运动的动画效果封装示例

    这篇文章主要介绍了JS实现匀速与减速缓慢运动的动画效果,结合实例形式分析了JavaScript封装结合定时器的页面元素动态变换效果动画相关操作技巧,需要的朋友可以参考下
    2018-08-08
  • JavaScript中日期函数的相关操作知识

    JavaScript中日期函数的相关操作知识

    日期函数是我们经常用到的知识点,下面通过本文给大家介绍JavaScript中日期函数的相关操作知识,非常不错,感兴趣的朋友一起学习吧
    2016-08-08
  • JS中关于ES6 Module模块化的跨域报错问题解决

    JS中关于ES6 Module模块化的跨域报错问题解决

    这篇文章主要介绍了JS中关于ES6 Module模块化的跨域报错,ES6模块化提供了export命令和import 命令,对于模块的导出和引入,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-07-07
  • js获取json中key所对应的value值的简单方法

    js获取json中key所对应的value值的简单方法

    下面小编就为大家带来一篇js获取json中key所对应的value值的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • 前端实现获取后端返回的文件流并下载三种方法

    前端实现获取后端返回的文件流并下载三种方法

    文件下载是最常见的流形式返回数据的应用场景之一,通过流形式返回文件内容,可以避免将整个文件加载到内存中,从而减少内存消耗,这篇文章主要介绍了前端实现获取后端返回的文件流并下载的三种方法,需要的朋友可以参考下
    2025-04-04
  • 原生微信小程序/uniapp使用空格占位符无效的解决办法

    原生微信小程序/uniapp使用空格占位符无效的解决办法

    最近需要在字体中间加空白占位符,在尝试使用 之后,还是不能使用,下面这篇文章主要给大家介绍了关于原生微信小程序/uniapp使用空格占位符无效的解决办法,需要的朋友可以参考下
    2023-02-02
  • uniapp实现微信小程序一键登录功能

    uniapp实现微信小程序一键登录功能

    这篇文章给大家介绍了uniapp实现微信小程序一键登录功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2024-10-10
  • 微信小程序实现地区选择伪五级联动

    微信小程序实现地区选择伪五级联动

    这篇文章主要为大家详细介绍了微信小程序实现地区选择伪五级联动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07

最新评论