0.1+0.2=0.30000000000000004
0.3-0.1=0.19999999999999998
0.1*0.2=0.020000000000000004
0.31/0.2=1.5499999999999998
计算出现精度丢失
计算机使用二进制表示数字,位数限制导致有些数字无法有限表示。js使用双精度存储,占用64位:
1位用来表示符号位
11位用来表示指数
52位表示尾数
0.1和0.2的二进制表示新式如下:
0.1 >> 0.0001 1001 1001 1001…(1001无限循环)
0.2 >> 0.0011 0011 0011 0011…(0011无限循环)
由于无限循环,无法正确表示。最后模仿十进制的四舍五入,0舍1进。所以导致计算机中部分浮点数运算时出现误差,丢失精度
1.直接使用对应类库number-precision
2.封装对应运算函数
// 浮点数 - 加
export function accAdd (arg1, arg2) {
var r1, r2, m, c;
try {
r1 = arg1.toString().split('.')[1].length;
} catch (e) {
r1 = 0;
}
try {
r2 = arg2.toString().split('.')[1].length;
} catch (e) {
r2 = 0;
}
c = Math.abs(r1 - r2);
m = Math.pow(10, Math.max(r1, r2));
if (c > 0) {
var cm = Math.pow(10, c);
if (r1 > r2) {
arg1 = Number(arg1.toString().replace('.', ''));
arg2 = Number(arg2.toString().replace('.', '')) * cm;
} else {
arg1 = Number(arg1.toString().replace('.', '')) * cm;
arg2 = Number(arg2.toString().replace('.', ''));
}
} else {
arg1 = Number(arg1.toString().replace('.', ''));
arg2 = Number(arg2.toString().replace('.', ''));
}
return (arg1 + arg2) / m;
}
// 浮点数 - 减
export function accSub (arg1, arg2) {
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)); // last modify by deeka //动态控制精度长度
n = r1 >= r2 ? r1 : r2;
return ((arg1 * m - arg2 * m) / m).toFixed(n);
}
// 浮点数 - 除以
export function accDiv (arg1, arg2) {
var t1 = 0;
var t2 = 0;
var r1;
var 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, t1 - t2);
}
// 浮点数 - 乘以
export function accMul (arg1, arg2) {
var m = 0;
var s1 = arg1.toString();
var 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)
);
}