1. Examples of calculation accuracy phenomena
Example 1. Addition
Example 2. Subtraction
Example 3. Multiplication
Example 3, division
2. Why does JS have calculation accuracy problems?
There is only one type of number in JavaScript, Number. That is to say, there is no integer at the bottom of the JavaScript language. All numbers are stored in the form of 64-bit floating-point numbers in the IEEE-754 standard format, and 1 and 1.0 are the same. Because some decimals are infinite in binary representation. JavaScript discards binary numbers beyond 53 bits, so be careful when comparing and computing decimals.
The IEEE Standard for Binary Floating-Point Arithmetic (IEEE 754) is the most widely used floating-point arithmetic standard since the 1980s and is used by many CPUs and floating-point arithmetic units. This standard defines formats for representing floating-point numbers (including negative zero-0 and denormal numbers), some special values (infinity (Inf) and not-a-number (NaN)), and the "floating-point number operators" for these values. "; it also specifies four rounding rules for numbers and five exceptions (including when and how exceptions occur).
3. Solutions
Project technology stack vue3+vite+ts
3.1. Method 1: expand the multiple at the same time and divide by the same multiple
(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. Method 2, toFixed retains the number of decimal places, and there are still precision problems
3.3. Method 3, mathjs - npm
pnpm add mathjs
Weekly Download 580197 (20230324)
method | operation | use | shipping result |
add |
addition | add(1, 2) |
3 |
subtract |
subtraction | subtract(2, 1) |
1 |
multiply |
multiplication | multiply(2, 2) |
4 |
divide |
division | divide(4, 2) |
2 |
round |
rounding | round(4.01) |
4 |
bignumber |
Convert to bigNumber type. For calculations with arbitrary precision, math.js supports the BigNumber data type, and bignumber returns a Decimal class, and the precision is still difficult to guarantee | bignumber(4.01) |
|
evaluate |
direct expression |
evaluate('(4.01 + 3) / 2') |
3.505 |
sqrt |
square root calculation |
sqrt(4) |
2 |
pow |
x to the power of y | pow(3,3) | 27 |
chain |
chain operation |
chain(3).add(4).multiply(2).done() |
14 |
atan2 |
Returns the arctangent of its argument quotient | atan2(15,30) |
0.4636476090008061 |
log | Returns the natural Log value of the given number (i.e. the base of e) | log(9) |
2.1972245773362196 |
pi |
PI | console.log('pi:', pi) |
3.141592653589793 |
e | Euler's constant and the base of natural logarithms, approximately 2.718 | console.log('e:', e) |
2.718281828459045 |
derivative |
To be verified | console.log('derivative:',derivative('x^2 + x', 'x')) |
|
matrix |
matrix operation |
matrix([0, 1, 2, 3, 4]) |
3.4. Method 4, bignumber.js - npm
Weekly Download 8826960 (20230324)
pnpm add bignumber.js
const num = new BigNumber(1234567890.0123456789) |
|||
const num1 = new BigNumber(123.123) |
|||
method | operation | use | operation result |
toFormat |
format |
num.toFormat() |
1,234,567,890.0123458 retains seven decimal places, the seventh place is rounded according to the eighth place |
toFormat |
format |
num.toFormat(3) |
1,234,567,890.012 to three decimal places |
toFormat |
format |
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 |
4. Welcome to exchange and correct, follow me, and learn together.
Reference link: