前端JavaScript处理小数精度问题(最佳实践)

前言:

针对于小数精度问题,本次我们主要推荐两种方式,一种是简单的函数封装,一种是使用第三方库big.js。

方法一:

自封装函数搭配parseFloat和toFixed解决小数精度问题,仅适用于解决一般性小数精度问题,适用于项目中小数问题比较少的项目。 

  /**
  * @description: 处理小数精度
  * @param {*} value 需要格式化的数字
  * @param {*} fixedNum 保留的小数位数,默认为2
  * @param {*} multiple 乘数,默认为1
  * @return {*} 
  */
  export const handleDecimalPrecision = (value, fixedNum = 2, multiple = 1) => {
    return parseFloat((value * multiple).toFixed(fixedNum))
  }

测试用例:

(传倍数multiple 是为了展示成百分比,比如30%)

0.1 + 0.2 //0.30000000000000004
handleDecimalPrecision(0.1 + 0.2) //0.3

handleDecimalPrecision(0.1 + 0.2,1,100) //30 传倍数multiple 是为了展示成百分比,比如30%

方法二:

使用第三方库big.js 。适用于精度问题比较多的项目,长期性解决精度问题。以下我们将展示一些常见的使用范围的场景,其他的深冷需求可移步至官方文档查看。

big.js特点

  • 简单的API
  • 比Java的BigDecimal更快、更小、更易于使用
  • 复制JavaScript数字的toExponential、toFixed和toPrecision方法
  • 可以访问的十进制浮点格式存储值
  • 全面的文档和测试集
  • 没有依赖关系,相对独立
  • 仅使用ECMAScript 3,无兼容性问题

安装big.js

npm install big.js -S

引入big.js

<script>
import Big from 'big.js'
</script>

示例(以vue为例):

code:

<template>
  <div class="app-container">
    <div>小数精度</div>
    <div>未处理 : 0.1 + 0.2 = {{sum_orgin}}</div>
    <div>bigjs处理 : 0.1 + 0.2 = {{sum_bigjs}}</div>
  </div>
</template>

<script setup>
import Big from 'big.js'

const num1 = 0.1
const num2 = 0.2
const sum_orgin = num1.value + num2.value
const sum_bigjs = Big(num1.value).plus(Big(num2.value))
</script>

效果图:

创建Big number数据

const num1 = Big(0.1)
或者
const num2 = new Big(0.2)

加法精度问题处理 - plus

0.1 + 0.2 //0.30000000000000004
0.7 + 0.1 //0.7999999999999999
0.2 + 0.4 //0.6000000000000001

Big(0.1).plus(Big(0.2)) //0.3
Big(0.1).plus(Big(0.24)) //0.34

减法精度问题 - minus

0.3 - 0.2 //0.09999999999999998
1.5 - 1.2 //0.30000000000000004

Big(0.3).minus(Big(0.2)) //0.1

乘法精度问题 - times

19.9 * 100 //1989.9999999999998
0.8 * 3 //2.4000000000000004
35.41 * 100 //3540.9999999999995

Big(19.9).times(Big(100)) //1990

除法精度问题 - div

0.3 / 0.1 //2.9999999999999996
0.69 / 10 //0.06899999999999999
Big(0.3).div(Big(0.1)) //3

保留小数位数(四舍五入) - round

1 / 3 //0.3333333333333333
Big(1).div(Big(3)).round(3) //0.333

big.js运算符说明

运算符

说明

abs

取绝对值

cmp

compare的缩写,即比较函数

div

除法

eq

equal的缩写,即相等比较

gt

大于

gte

小于等于,e表示equal

lt

小于

lte

小于等于,e表示equal

minus

减法

mod

取余

plus

加法

pow

次方

prec

按精度舍入,参数表示整体位数

round

按精度舍入,参数表示小数点后位数

sqrt

开方

times

乘法

toExponential

转化为科学计数法,参数代表精度位数

toFied

补全位数,参数代表小数点后位数

toJSON/toString

转化为字符串

toPrecision

按指定有效位数展示,参数为有效位数

toNumber

转化为JavaScript中number类型

valueOf

包含负号(如果为负数或者-0)的字符串

bigjs官网文档 

拓展

小数为什么失去了精度?

在计算机中,小数(浮点数)的表示和存储方式决定了它们可能会失去精度。这是因为计算机使用二进制(0和1)来表示数字,而二进制无法精确表示某些十进制小数。例如,十进制的 0.1 在二进制中是一个无限循环小数,无法精确表示。这种表示上的限制导致了小数在计算机中的精度问题。

原因:

  1. 二进制表示:计算机使用二进制(0和1)来表示数字。然而,二进制无法精确表示某些十进制小数,例如 0.1、0.2、0.3 等。这些小数在二进制中是无限循环小数,无法精确表示。

  2. 存储限制:计算机中的浮点数使用有限的位数来表示,包括符号位、指数位和尾数位。这种有限的表示方式限制了浮点数的精度。

  3. 舍入误差:在将十进制小数转换为二进制浮点数时,可能会出现舍入误差。这种舍入误差会导致小数的精度下降。

解决方法:

  1. 使用定点数:定点数是一种特殊的浮点数表示方式,它将小数点固定在某个位置。使用定点数可以避免二进制表示带来的精度问题,但需要手动处理小数点的位置。

  2. 使用高精度库:一些编程语言提供了高精度库,可以处理大数和浮点数的精确计算。这些库使用更大的位数来表示数字,从而提高了精度。

  3. 四舍五入:在计算过程中,可以使用四舍五入等方法来减少舍入误差,提高小数的精度。

  4. 使用整数表示:在某些情况下,可以将小数转换为整数来避免精度问题。例如,将 0.01 转换为 1,将 0.02 转换为 2,以此类推。

需要注意的是,虽然上述方法可以减少小数的精度问题,但并不能完全避免。在处理小数时,需要根据具体的应用场景和需求来选择合适的方法。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零凌林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值