Javascipt中精確小數運算的實現

之前的舊文,貌似仍是挺有用的,在這裏記一下避免丟失:ide

基於Web的應用程序,常常須要在頁面中做些簡單的計算,用做數據提交前的驗證,或者給用戶提供更友好的信息。但因爲十進制小數並不總能用二進制小數精確表示,在進行小數運算時,常常會出現「莫明其妙」的偏差,好比「33*2.46=81.179999999999999」之類的。若是要在頁面上顯示計算結果,特別是當這個結果表示金額的時候,偏差一般是不可容忍的。code

網上有人說Javasript不能作精確運算,因此會出現偏差云云。這固然是不對的,這種狀況應該是由計算機二進制表示的本質決定的。應該說,Javascript的表現其實還好一些,由於在數字進行運算以前,咱們老是能夠獲得它的精確表示(字符串)。對象

解決問題的基本思路就是犧牲速度換精度,逐位進行運算,而且本身在程序邏輯中實現進位。爲此,Java提供了BigDecimal類。而在Javascript中,咱們就沒這麼幸運了,沒有現成的類庫可供使用。多是制訂規範的人也認爲不必使用JS來作「科學計算」吧。ip

我之前作的項目中,常常會碰到計算金額總價、合計、總計之類的「商業計算」,對精確小數運算的需求仍是比較迫切的,因此本身開發了一個小數運算的「類」。實現這個類的時候,使用了投機取巧的辦法:把小數轉換爲整數,運算完成後,再轉換回去。它惟一能解決的問題就是:避免十進制小數和二進制小數之間的轉換偏差;它不能提升運算的精度(有效數字),也不能擴大數字的表示範圍。
使用方法以下:ci

//使用數字的literal表示,建立一個Decimal對象    
var d1 = new Decimal(3.68);    
//調用該對象的四則運算方法,獲得一個新的Decimal對象   
var res=d1.add(2.25);    
//調用該對象的valueOf方法,獲得數值   
alert( res.valueOf() ); //顯示 5.93    
//或者調用該對象的toString方法,獲得數值的字符串表示   
alert( res.toString() ); //顯示 5.93    
  
//可用的運算方法對應四則運算的+、-、×、÷   
var d1 = new Decimal(3.68);   
var res=d1.add(2.25);   
assertEquals("3.68+2.25", "5.93", res.toString());   
  
var d1 = new Decimal(3.68);   
var res=d1.minus(2.25);   
assertEquals("3.68-2.25", "1.43", res.toString());   
  
var d1 = new Decimal(2.22);   
var res=d1.multiply(3.33);   
assertEquals("2.22*3.33", 7.3926, res.valueOf());   
  
var d1 = new Decimal(6.66);   
var res=d1.divide(2.22);   
assertEquals("6.66/2.22", 3, res.valueOf());

源碼在這裏下載:https://pan.baidu.com/s/1i4Gugqp開發

相關文章
相關標籤/搜索