一、计算精度现象举例
举例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)
3
subtract
减法
subtract(2, 1)
1
multiply
乘法
multiply(2, 2)
4
divide
除法
divide(4, 2)
2
round
四舍五入
round(4.01)
4
bignumber
转换为bigNumber类型。对于具有任意精度的计算,math.js支持BigNumber数据类型,bignumber返回一个Decimal类,精度依然难以保证
bignumber(4.01)
evaluate
直接运算表达式
evaluate('(4.01 + 3) / 2')
3.505
sqrt
平方根计算
sqrt(4)
2
pow
x 的 y 次幂值pow(3,3)27
chain
链式操作
chain(3).add(4).multiply(2).done()
14
atan2
返回其参数商的反正切值
atan2(15,30)
0.4636476090008061log返回给定数字的自然Log值(即e的底数)
log(9)
2.1972245773362196
pi
圆周率
console.log('pi:', pi)
3.141592653589793e欧拉常数和自然对数的基数,约为 2.718
console.log('e:', e)
2.718281828459045
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 参考手册
版权归原作者 snow@li 所有, 如有侵权,请联系我们删除。