关于js的浮点数计算问题记录

为什么 js 会有浮点数计算精度问题?

在 JavaScript 中,整数和浮点数都归属于 Number 类型,数字都是 64 位浮点数形式存储的,这样就会导致浮点数运算时候会出现一些问题,下面是一些例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let numberA = 0.1 + 0.2;
let numberB = 1.5 - 1.2;
let numberC = 19.9 * 100;
let numberD = 0.3 / 0.1;
console.log(
"numberA ",
numberA,
" numberB ",
numberB,
" numberC ",
numberC,
" numberD ",
numberD
);

// output numberA 0.30000000000000004 numberB 0.30000000000000004 numberC 1989.9999999999998 numberD 2.9999999999999996

上述案例的计算结果并不符合我们数学计算逻辑,这样导致我们在进行一些复杂的浮点数运算时候出现偏差,业务场景多见于财务和商品金额计算,在项目中我们做了相关数学方法兼容处理,以下是我们的处理方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
mathHandle = {
add: (arg1: any, arg2: any) => {
var r1, r2, m;
try {
r1 = arg1.toString().split(".")[1].length;
} catch (e) {
r1 = 0;
}
try {
r2 = arg2.toString().split(".")[1].length;
} catch (e) {
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2));
return (arg1 * m + arg2 * m) / m;
},
subtract: (arg1: any, arg2: any) => {
var r1, r2, m, n;
try {
r1 = arg1.toString().split(".")[1].length;
} catch (e) {
r1 = 0;
}
try {
r2 = arg2.toString().split(".")[1].length;
} catch (e) {
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2));
//动态控制精度长度
n = r1 >= r2 ? r1 : r2;
return ((arg1 * m - arg2 * m) / m).toFixed(n);
},
multiply: (arg1: any, arg2: any) => {
var m = 0,
s1 = arg1.toString(),
s2 = arg2.toString();
try {
m += s1.split(".")[1].length;
} catch (e) {}
try {
m += s2.split(".")[1].length;
} catch (e) {}
return (
(Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) /
Math.pow(10, m)
);
},
divide: (arg1: any, arg2: any) => {
var t1 = 0,
t2 = 0,
r1,
r2;
try {
t1 = arg1.toString().split(".")[1].length;
} catch (e) {}
try {
t2 = arg2.toString().split(".")[1].length;
} catch (e) {}
r1 = Number(arg1.toString().replace(".", ""));
r2 = Number(arg2.toString().replace(".", ""));
return (r1 / r2) * Math.pow(10, t2 - t1);
},
};

上述代码已经完全应用于业务代码中,并且暂未出现问题,网上还有更多更完善的解决方案(mathjs)等,可供大家参考。


关于js的浮点数计算问题记录
https://blog.funfe.cn/2023/11/30/20231130112354/
作者
李鹏杰
发布于
2023年11月30日
许可协议