https://blog.csdn.net/qinshenxue/article/details/43671763
說明
眾所周知,js在計算浮點數時候,結果可能會不准確。比如:(在chrome中的運算結果)
2.2 + 2.1 = 4.300000000000001
2.2 - 1.9 = 0.30000000000000027
2.2 * 2.2 = 4.840000000000001
2.1 / 0.3 = 7.000000000000001
網上流傳的代碼(有bug)
網上流傳的優化后的代碼如下(有問題的代碼,請勿使用)
function add(a, b) {
var c, d, e;
try {
c = a.toString().split(".")[1].length;
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length;
} catch (f) {
d = 0;
}
return e = Math.pow(10, Math.max(c, d)), (a * e + b * e) / e;
}
function sub(a, b) {
var c, d, e;
try {
c = a.toString().split(".")[1].length;
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length;
} catch (f) {
d = 0;
}
return e = Math.pow(10, Math.max(c, d)), (a * e - b * e) / e;
}
function mul(a, b) {
var c = 0,
d = a.toString(),
e = b.toString();
try {
c += d.split(".")[1].length;
} catch (f) {}
try {
c += e.split(".")[1].length;
} catch (f) {}
return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c);
}
function div(a, b) {
var c, d, e = 0,
f = 0;
try {
e = a.toString().split(".")[1].length;
} catch (g) {}
try {
f = b.toString().split(".")[1].length;
} catch (g) {}
return c = Number(a.toString().replace(".", "")), d = Number(b.toString().replace(".", "")), c / d * Math.pow(10, f - e);
}
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
原理就是將浮點數轉化為整數來計算。
問題代碼測試
但是上面的優化方法真的解決問題了嗎,我們可以簡單做下測試。
測試代碼如下:(測試運算中加法)
function test(){
var a = (Math.random() * 100).toFixed(2) - 0;
var b = (Math.random() * 1000).toFixed(2) - 0;
var result = add(a, b);
if ((result + '').length > 10) {
console.error('被加數:'+a,'加數:'+b, '結果:'+result);
return;
}
setTimeout(function() {
test();
}, 10);
}
test();
1
2
3
4
5
6
7
8
9
10
11
12
13
問題代碼測試結果
瀏覽器控制台很快就打印了結果,說明被測試的加法運算代碼存在運算不准確的問題。
測試運行結果:
問題代碼出錯原因
既然上面的代碼有問題,那么出錯的點在哪里,我們就以計算錯誤的數字來調試代碼。
被加數:19.36 加數:601.19 結果:620.5500000000001
調試的過程及結果如下:
我們發現原來是其中的乘法計算錯誤。
修正方法
網上有一些版本你會發現在最終返回結果的時候加上了toFixed,這是一種解決方法。
另外既然是乘法出錯,我們何不將乘法換成優化后的乘法了。比如修改后的加法如下:
function add(a, b) {
var c, d, e;
try {
c = a.toString().split(".")[1].length;
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length;
} catch (f) {
d = 0;
}
return e = Math.pow(10, Math.max(c, d)), (mul(a, e) + mul(b, e)) / e;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
然后用上面的方法進行測試,等了”一天“,控制台也沒打印了。說明這次真的把問題解決了。
最終版(正確版)
function add(a, b) {
var c, d, e;
try {
c = a.toString().split(".")[1].length;
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length;
} catch (f) {
d = 0;
}
return e = Math.pow(10, Math.max(c, d)), (mul(a, e) + mul(b, e)) / e;
}
function sub(a, b) {
var c, d, e;
try {
c = a.toString().split(".")[1].length;
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length;
} catch (f) {
d = 0;
}
return e = Math.pow(10, Math.max(c, d)), (mul(a, e) - mul(b, e)) / e;
}
function mul(a, b) {
var c = 0,
d = a.toString(),
e = b.toString();
try {
c += d.split(".")[1].length;
} catch (f) {}
try {
c += e.split(".")[1].length;
} catch (f) {}
return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c);
}
function div(a, b) {
var c, d, e = 0,
f = 0;
try {
e = a.toString().split(".")[1].length;
} catch (g) {}
try {
f = b.toString().split(".")[1].length;
} catch (g) {}
return c = Number(a.toString().replace(".", "")), d = Number(b.toString().replace(".", "")), mul(c / d, Math.pow(10, f - e));
}
---------------------
作者:筆心
來源:CSDN
原文:https://blog.csdn.net/qinshenxue/article/details/43671763
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!