一、计算精度现象举例

举例1、加法

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

举例2、减法 

 JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

举例3、乘法

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

举例3、除法

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

二、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

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

3.2、方法二,toFixed保留小数位数,依然存在精度问题

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

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)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

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.4636476090008061
log 返回给定数字的自然Log值(即e的底数)

log(9)

2.1972245773362196

pi

圆周率

console.log('pi:', pi)

3.141592653589793
e 欧拉常数和自然对数的基数,约为 2.718

console.log('e:', e)

2.718281828459045

derivative

待考证

console.log('derivative:',derivative('x^2 + x', 'x'))

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

matrix

矩阵操作

matrix([0, 1, 2,  3, 4])

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

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)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

minus

减法

num1.minus(1.1)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

times

乘法

num1.times(2)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

div

除法

num1.div(2)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

mod

取余

num1.mod(2)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

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()

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

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)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

minus

减法

num1.minus(1.1)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

times

乘法

num1.times(2)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

div

除法

num1.div(2)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

mod

取余

num1.mod(2)

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

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))

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

minus

减法

num1.minus(new Decimal(1.1))

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

times

乘法

num1.times(new Decimal(2))

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

div

除法

num1.div(new Decimal(2))

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

mod

取余

num1.mod(new Decimal(2))

JavaScript:解决计算精度问题/mathjs/bignumber.js/big.js/decimal.js

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 参考手册

发表回复