轉自:http://superivan.iteye.com/blog/963628
[1] 精確的浮點運算:
在Java里面,有時候為了保證數值的準確性需要精確的數據,先提供一個例子就可以發現問題了:
public class FloatNumberTester { public static void main(String args[]){ 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); } }
按照我們的期待,上邊應該是什么結果呢,但是看輸出我們就會發現問題了:
這樣的話這個問題就相對嚴重了,如果我們使用123.3元交易,計算機卻因為1.2329999999999999而拒絕了交易,豈不是和實際情況大相徑庭。
[2] 四舍五入:
另外的一個計算問題,就是四舍五入。但是Java的計算本身是不能夠支持四舍五入的,比如:
public class GetThrowTester { public static void main(String args[]){ System.out.println(4.015 * 100.0); } }
這個輸出為:
401.49999999999994
所以就會發現這種情況并不能保證四舍五入,如果要四舍五入,只有一種方法java.text.DecimalFormat:
import java.text.DecimalFormat; public class NumberFormatMain { public static void main(String args[]){ System.out.println(new DecimalFormat("0.00").format(4.025)); System.out.println(new DecimalFormat("0.00").format(4.024)); } }
上邊代碼輸出為:
4.02 4.02
發現問題了么?因為DecimalFormat使用的舍入模式, 舍入模式 詳情參見本文最后部分。
[3] 浮點輸出:
Java浮點類型數值在大于9999999.0就自動轉化成為科學計數法,看看下邊的例子:
public class FloatCounter { public static void main(String args[]){ System.out.println(9969999999.04); System.out.println(199999999.04); System.out.println(1000000011.01); System.out.println(9999999.04); } }
9.96999999904E9 1.9999999904E8 1.00000001101E9 9999999.04
但是有時候我們不需要科學計數法,而是轉換成為字符串,所以這樣可能會有點麻煩。
總結:
所以在項目當中,對于浮點類型以及大整數的運算 還是盡量不要用double,long等基本數據類型以及其包裝類,還是用Java中提供的BigDecimal,BigInteger等大數值類型來代替吧。
但這里特別說明一下BigDecimal類的兩個構造函數的區別,他們分別是:
new BigDecimal(String val ) 和 new BigDecimal(double val )
先看例子:
public class BigDecimalMain { public static void main(String args[]){ System.out.println(new BigDecimal(123456789.01).toString()); System.out.println(new BigDecimal("123456789.01").toString()); } }
輸出結果有一次令人意外了,同時兩者之間的區別也一目了然了:
123456789.01000000536441802978515625 123456789.01
所以在 就是想利用double原始類型進行了相關計算之后再轉成BigDecimal類型 的場合下,為了防止精度出現偏離,建議使用參數為String類型的該構造方法。即new BigDecimal(String val )。
補充:
- BigDecimal都是不可變的(immutable)的,在進行每一步運算時,都會產生一個新的對象,由于創建對象會引起開銷,因此它們不適合于大量的數學運算,應盡量使用long、float、double等基本類型做科學計算或者工程計算。設計BigInteger與BigDecimal的目的是用來精確地表示大整數和小數,常用于商業計算中。
- BigDecimal夠造方法的參數類型有4種,其中的兩個用BigInteger構造,另一個是用double構造,還有一個使用String構造。應該避免使用double構造BigDecimal,因為:有些數字用double根本無法精確表示,傳給BigDecimal構造方法時就已經不精確了。比如,new BigDecimal(0.1)得到的值是0.1000000000000000055511151231257827021181583404541015625。使用new BigDecimal("0.1")得到的值是0.1。因此,如果需要精確計算,用String構造BigDecimal,避免用double構造,盡管它看起來更簡單!
- equals()方法認為0.1和0.1是相等的,返回true,而認為0.10和0.1是不等的,結果返回false。方法compareTo()則認為0.1與0.1相等,0.10與0.1也相等。所以在從數值上比較兩個BigDecimal值時,應該使用compareTo()而不是 equals()。
- 另外還有一些情形,任意精度的小數運算仍不能表示精確結果。例如,1除以9會產生無限循環的小數 .111111...。出于這個原因,在進行除法運算時,BigDecimal可以讓您顯式地控制舍入。
![]() |
不含病毒。www.avast.com |