一、计算精度现象举例
举例1、加法
举例2、减法
举例3、乘法
举例3、除法
二、JS为什么会有计算精度的问题
JavaScript 内部只有一种数字类型Number,也就是说,JavaScript 语言的底层根本没有整数,所有数字都是以IEEE-754标准格式64位浮点数形式储存,1与1.0是相同的。因为有些小数以二进制表示位数是无穷的。JavaScript会把超出53位之后的二进制舍弃,所以涉及小数的比较和运算要特别小心。
IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number)),一些特殊数值(无穷(Inf)与非数值(NaN)),以及这些数值的“浮点数运算符”;它也指明了四种数值舍入规则和五种例外状况(包括例外发生的时机与处理方式)。
三、解决方法
项目技术栈vue3+vite+ts
3.1、方法一,同时扩大倍数再除以相同的倍数
(x * 10 ^ n + y * 10 ^ n)/ 10 ^ n
0.1 +0.2 // 0.30000000000000004 (0.1 *10 + 0.2 *10) / 10 // 0.3
3.2、方法二,toFixed保留小数位数,依然存在精度问题
3.3、方法三,mathjs - npm
pnpm add mathjs
Weekly Download 580197 (20230324)
add
add(1, 2)
subtract
subtract(2, 1)
multiply
multiply(2, 2)
divide
divide(4, 2)
round
round(4.01)
bignumber
bignumber(4.01)
evaluate
直接运算表达式
evaluate('(4.01 + 3) / 2')
sqrt
平方根计算
sqrt(4)
pow
chain
链式操作
chain(3).add(4).multiply(2).done()
atan2
atan2(15,30)
log(9)
pi
console.log('pi:', pi)
console.log('e:', e)
derivative
console.log('derivative:',derivative('x^2 + x', 'x'))
matrix
矩阵操作
matrix([0, 1, 2, 3, 4])
3.4、方法四,bignumber.js - npm
Weekly Download 8826960 (20230324)
pnpm add bignumber.js
const num = new BigNumber(1234567890.0123456789)
const num1 = new BigNumber(123.123)
toFormat
格式化
num.toFormat()
1,234,567,890.0123458 保留了七位小数,第七位依据第八位四舍五入
toFormat
格式化
num.toFormat(3)
1,234,567,890.012 保留三位小数
toFormat
格式化
num.toFormat(13)
1,234,567,890.012 保留十三位小数,实际还是保留了七位小数,第七位依据第八位四舍五入,然后位数用0补足
plus
num1.plus(1.1)
minus
num1.minus(1.1)
times
num1.times(2)
div
num1.div(2)
mod
取余
num1.mod(2)
x.eq(y)
isEqualTo--是否相等
num.eq(num1)
false
x.gt(y)
isGreaterThan--是否大于
num.gt(num1)
true
x.gte(y)
isGreaterThanOrEqualTo--是否大于等于
num.gte(num1)
true
x.lt(y)
isLessThan--是否小于
num.lt(num1)
false
x.lte(y)
isLessThanOrEqualTo--是否小于等于
num.lte(num1)
false
negated
取非,改变数字的正负号
num.negated()
3.5、方法五,big.js - npm
Weekly Download 21,339,420 (20230324)
pnpm add @types/big.js
const num = new Big(1234567890.0123456789)
const num1 = new Big(123.123)
plus
num1.plus(1.1)
minus
num1.minus(1.1)
times
num1.times(2)
div
num1.div(2)
mod
取余
num1.mod(2)
x.eq(y)
isEqualTo--是否相等
num.eq(num1)
false
x.gt(y)
isGreaterThan--是否大于
num.gt(num1)
true
x.gte(y)
isGreaterThanOrEqualTo--是否大于等于
num.gte(num1)
true
x.lt(y)
isLessThan--是否小于
num.lt(num1)
false
x.lte(y)
isLessThanOrEqualTo--是否小于等于
num.lte(num1)
false
3.6、方法六,decimal.js - npm
Weekly Download 16,251,713 (20230324)
pnpm add decimal.js
const num = new Big(1234567890.0123456789)
const num1 = new Big(123.123)
plus
num1.plus(new Decimal(1.1))
minus
num1.minus(new Decimal(1.1))
times
num1.times(new Decimal(2))
div
num1.div(new Decimal(2))
mod
取余
num1.mod(new Decimal(2))
x.eq(y)
isEqualTo--是否相等
num.eq(num1)
false
x.gt(y)
isGreaterThan--是否大于
num.gt(num1)
true
x.gte(y)
isGreaterThanOrEqualTo--是否大于等于
num.gte(num1)
true
x.lt(y)
isLessThan--是否小于
num.lt(num1)
false
x.lte(y)
isLessThanOrEqualTo--是否小于等于
num.lte(num1)
false
四、欢迎交流指正,关注我,一起学习。
参考链接:
JavaScript Math 参考手册