Java精確運算(BigDecimal)__Java
來源:互聯網
上載者:User
(1)、浮點數精確計算 勝利油田三流合一項目中一直存在一個問題,就是每次報表統計的物資金額和實際的金額要差那麼幾分錢,和實際金額不一致,讓客戶覺得總是不那麼舒服,原因是因為我們使用java的浮點類型double來定義物資金額,並且在報表統計中我們經常要進行一些運算,但Java中浮點數(double、float)的計算是非精確計算,請看下面一個例子: System.out.println(0.05 + 0.01); System.out.println(1.0 - 0.42); System.out.println(4.015 * 100); System.out.println(123.3 / 100); 你的期望輸出是什麼。可實際的輸出確實這樣的: 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999 這個問題就非常嚴重了,如果你有123.3元要購買商品,而電腦卻認為你只有123.29999999999999元,錢不夠,電腦拒絕交易。 (2)、四捨五入 是否可以四捨五入呢。當然可以,習慣上我們本能就會這樣考慮,但四捨五入意味著誤差,商業運算中可能意味著錯誤,同時Java中也沒有提供保留指定位元的四捨五入方法,只提供了一個Math.round(double d)和Math.round(float f)的方法,分別返回長整型和整型值。round方法不能設定保留幾位小數,我們只能象這樣(保留兩位): public double round(double value){ return Math.round( value * 100 ) / 100.0; } 但非常不幸的是,上面的代碼並不能正常工作,給這個方法傳入4.015它將返回4.01而不是4.02,如我們在上面看到的 4.015 * 100 = 401.49999999999994 因此如果我們要做到精確的四捨五入,這種方法不能滿足我們的要求。 還有一種方式是使用java.text.DecimalFormat,但也存在問題,format採用的舍入模式是ROUND_HALF_DOWN(舍入模式在下面有介紹),比如說4.025保留兩位小數會是4.02,因為.025距離” nearest neighbor”(.02和.03)長度是相等,向下舍入就是.02,如果是4.0251那麼保留兩位小數就是4.03。 System.out.println(new java.text.DecimalFormat("0.00").format(4.025)); System.out.println(new java.text.DecimalFormat("0.00").format(4.0251)); 輸出是 4.02 4.03 (3)、浮點數輸出(科學記號標記法) Java浮點型數值在大於9999999.0就自動轉化為科學記號標記法來表示,我們看下面的例子: System.out.println(999999999.04); System.out.println(99999999.04); System.out.println(10000000.01); System.out.println(9999999.04); 輸出的結果如下: 9.9999999904E8 9.999999904E7 1.000000001E7 9999999.04 但有時我們可能不需要科學記號標記法的表示方法,需要轉換為字串,還不能直接用toString()等方法轉換,很煩瑣。 BigDecimal介紹 BigDecimal是Java提供的一個不變的、任意精度的有符號十進位數對象。它提供了四個構造器,有兩個是用BigInteger構造,在這裡我們不關心,我們重點看用double和String構造的兩個構造器(有關BigInteger詳細介紹請查閱j2se API文檔)。 BigDecimal(double val) Translates a double into a BigDecimal. BigDecimal(String val)