1. 程式人生 > >由BigDecimal引發的思考

由BigDecimal引發的思考

本文綜合網上牛人以及Java API所寫,還有自己的一些專案經歷。主要實用工具Eclipse3.5、jdk1.6,測試框架JUnit4等。

floatdouble只能用來做科學計算或者是工程計算,在商業計算中我們要用java.math.BigDecimal

                                                                                                                                       -----Effective Java

看一個小例子:

 

測試結果:

 

讓人不可思議,怎麼會與自己的想象差的那麼遠!但,現實確實如此!

Java中的簡單浮點數型別floatdouble不能夠進行運算。不光是Java,在其它很多程式語言中也有這樣的問題。在大多數情況下,計算的結果是準確的,但是多試幾次(可以做一個迴圈)就可以試出類似上面的錯誤。

再者,Math類、DecimalFormat類有對應的處理資料的方法。例項程式碼:

 

顯示結果:

 

哎,還是讓人很失望。

難道在工程中,我們就這樣計算嗎?當然不是,Java還沒有“挫”,呵呵!下面談談BigDecimal。

BigDecimal有很多構造方法,詳看api文件。這裡主要說說下面兩個構造方法:

 

關於其他的構造方法,這裡不贅述,舉一反三吧!

這兩個構造方法,建議採用第二個,具體原因在api上解釋的很清楚。

 

翻譯一下:

 

使用BigDecimal,可以獲得交準確的計算結果,並且可以自己定義小數精度,具有一定的靈活性。例項程式碼:

 

其中,BigDecimal有很多常量欄位。ROUND_HALF_UP表示四捨五入。例項程式碼:

 

在JUnit4的幫助下,很好地完成了許多測試,解開了很多疑惑。如果你不明白最好還是多加測試。也許,你有更多的發現。

在好奇心的驅使下,又看看BigDecimal原始碼,主要涉及到其valueOf(double val)方法,該方法是靜態方法,原始碼如下:

 

可以看出,valueOf(double val)方法以BigDecimal(Double.toString(val))方式返回一個BigDecimal物件。所以在以double為源的時候創

建BigDecimal物件,可以採用該方法。修改上面例項程式碼如下:

 

在看原始碼的時候,經常看到別人使用valueof**方法,難道它有什麼與眾不同嗎?研究一下ing.....

首先,研究一下Integer的建立方式:

 

根據註釋來看,equals比較之後都是true,這很好理解。因為Integer重寫了equals方法,只要內容相同,equals比較就是true。再者new方式產出的物件用”=“比較肯定是false,但是為什麼同樣是valueOf,一個是true,而另一個卻是false???!!!

不要急,看看Integer原始碼:

 

IntegerCache是靜態內部類。從原始碼可以看出使用valueOf方法建立Integer例項時:

當這個值在-128和127之間時,會用快取儲存起來,供多次使用,以節約記憶體。 
如果不在這個範圍內,則建立一個新的Integer物件。 再看一個例項:

 

暈。。居然false,why????

反編譯一下這段程式碼,看看它神祕的面紗。

 

哦,原來如此。自動裝箱使用的就是valueOf方法,額的神啊!那麼自動拆箱是什麼原理?

 

另外,算是提示吧?!

初始化一個字串,  String s1 = "s1"; 這樣的程式碼肯定比  String s2 = new String("s2");程式碼強,將其他型別的值轉換成String的時候,valueof方法比new方法效率也高。 

文章到此為止,希望對你有用!

非常感謝:

這篇文章引用了他們的某些程式碼片段,如果不是他們的無私奉獻,估計我沒有勇氣和能力寫出這篇文章,再次感謝他們,向他們學習!!!