標籤:
眾所周知,javascript對於浮點數的運算一直都是有問題的,比如0.2+0.1 結果是 0.30000000000000004。
下面是我的解決方案,先貼代碼了:
var calMath = (function() { var isFloat = function(a) { var reg = /\d.\d+/g return reg.test(a) } var getFloatDigit = function(a) { var digit, len a = a.toString() digit = a.split(".") len = digit[1] == undefined ? 0 : digit[1].length return len } var allArithmetic = function(type, a, b) { var c, gfd_a, gfd_b, baseLen, baseMulti var a = Number(a), b = Number(b) if (isFloat(a) || isFloat(b)) { gfd_a = getFloatDigit(a) gfd_b = getFloatDigit(b) baseLen = gfd_a >= gfd_b ? gfd_a : gfd_b baseMulti = Math.pow(10, baseLen) a = type != "add" ? Number(a.toString().replace(".", "")) : a b = type != "add" ? Number(b.toString().replace(".", "")) : b if (type == "add") { c = ((a * baseMulti + b * baseMulti) / baseMulti).toFixed(baseLen) } else if (type == "multi") { c = (a * b) / Math.pow(10, gfd_a + gfd_b) } else if (type == "divi") { c = ((a / b) * Math.pow(10, gfd_b - gfd_a)) } } else { if (type == "add") { c = a + b } else if (type == "multi") { c = a * b } else if (type == "divi") { c = a / b } } return c } return { add: function(a, b) { return allArithmetic("add", a, b) }, sub: function(a, b) { return allArithmetic("add", a, -b) }, multi: function(a, b) { return allArithmetic("multi", a, b) }, divi: function(a, b) { return allArithmetic("divi", a, b) } }})()
思路就是:
1. 判定是否是浮點數。
2. 如果不是浮點數,就選擇常規的運算方法。
3. 如果是浮點數,則先取浮點數後面個數(即小數點的位元)。
4. 如果是浮點數的加減法運算,則比較他們小數點後的位元,取較大的那個,暫且稱之為n,這個數有什麼用呢?就是先讓我們的浮點數都變成整數(小數乘以10的n次方),然後在重新變成浮點數(結果再除以10的n次方),整數做加減法總沒事了吧?其實並不一定,有些情況,浮點數乘以10的次方時,出來的數也會有“尾巴”,但是這個“尾巴”的誤差相對來說比較小,所以我們利用toFixed(n)來處理掉它就ok了。
5. 如果是浮點數的乘法運算,其實思路跟上面的類似,先將他們小數點後的位元相加,取得的值繼續叫他小n吧,小n暫且不管他,我們這裡換種讓浮點數變成整數的方式,就是直接把小數點給去掉,理由就是剛剛在加減法時提到的,如果用10的n次方讓小數變整數,其實有可能出現誤差很小的浮點數的,那在加減法中我們可以有補救措施,但是在乘法中,一個點0.00000000x的小數出現了之後,再補救就不可能了。那我們這裡的小n有什麼用呢,當然是把整數再變回小數啦。
6. 如果是浮點數的除法運算,思路跟乘法基本一致,看著代碼自己思考吧。
console.log(calMath.add(0.2,0.1)) //結果是0.3哦
javascript浮點數運算修正