- javascript中的數字都是雙精度的浮點數。
- JavaScript中的整數並不是一個獨立的數據類型,而是浮點數的一個子集。
浮點數的坑
我們看下面的例子
在瀏覽器的console 控制台上我們分別進行以下的浮點數運算

通過控制台的運算,我們可以很驚奇的看到答案,有些運算結果竟然和我們想像的不一樣,比如0.1+0.2的返回結果不是0.3,而是0.30000000000000004。
這究竟是啥原因?
1,首先要肯定的是這不是瀏覽器的問題,而是由於浮點數的精度導致的。
2,浮點數的精度問題並不是JavaScript所獨有的,例如在java中,我們運行以下代碼,同樣會輸出和JavaScript中一樣的結果。
double dd = 0.1+0.2; System.out.println(dd);//0.30000000000000004?
why?
因為電腦永遠都是按照二進制進行運算的,我們輸入的十進制數在轉化為二進制數時,並不總如人意,意思是說有些十進制並不能用准確的二進制數表示。
十進制小樹轉二進制表示
我們來看下十進制小樹轉二進制表示的過程,小數位乘以2,取整,小數部分繼續乘以2,再取整,直到小數部分為0為止,然后將取整位按順序排列。
由此方法我們可以看到以下一些十進制小數的二進制表示。
十進制 二進制 0.1 0.0001 1001 1001 1001 ... 0.2 0.0011 0011 0011 0011 ... 0.3 0.0100 1100 1100 1100 ... 0.4 0.0110 0110 0110 0110 ... 0.5 0.1 0.6 0.1001 1001 1001 1001 ...
我們發現有些小數的二進制表示位數是無限循環的,這就造成了浮點數精度上的問題。
比如十進制的1.1,在用二進制表示的時因為存在二進制位無限循環的表示,實際值為1.0999999999...無限接近與1.1
解決方案
常用的一種解決方法就是將浮點數轉化為整數進行運算,以下是一些封裝好的關於浮點運算的方法,而且經過測試,加減乘除運算都會達到自己想要的結果。
//求和 function add(num1,num2){ var r1,r2,m; try{ r1 = num1.toString().split('.')[1].length; }catch(e){ r1 = 0 } try{ r2 = num2.toString().split('.')[1].length; }catch(e){ r2 = 0 } m = Math.pow(10,Math.max(r1,r2)); return Math.round(num1*m + num2*m)/m; }
//相減 function sub(num1,num2){ var r1,r2,m; try{ r1 = num1.toString().split('.')[1].length; }catch(e){ r1 = 0; } try{ r2 = num1.toString().split('.')[1].length; }catch(e){ r2 = 0; } m = Math.pow(10,Math.max(r1,r2)); n = (r1 >= r2) ? r1 : r2; return (Math.round(num1 * m - num2*m) / m).toFixed(n); }
//相乘 function mul(num1,num2){ var m = 0,r1,r2; var s1 = num1.toString(); var s2 = num2.toString(); try{ m += s1.split('.')[1].length }catch(e){ } try{}catch(e){ m += s2.split('.')[1].length }catch(e){ } r1 = Number(num1.toString().replace(".","")); r2 = Number(num2.toString().replace(".","")); return r1 * r2 / Math.pow(10,m); }
//相除 function accDiv(){ var t1,t2,r1,r2; try{ t1 = num1.toString().split('.')[1].length; }catch(e){ t1 = 0; } try{}catch(e){ t2 = num2.toString().split('.')[1].length; }catch(e){ t2 = 0; } r1 = Number(num1.toString().replace(".","")); r2 = Number(num2.toString().replace(".","")); return (r1 / r2)*Math.pwo(10,t2-t1); }
