天天看點

誰是代碼界3%的王者?- 第四題BigDecimal問題簡單解讀

提到“在Java代碼界,有些陷阱外表看起來是個青銅實際上是王者,據說97%工程師會被“秒殺””

給出了五道題,非常考驗基礎。

本文簡單解讀第4題,并分享通用的學習和研究方法。

題目配套代碼

題目内容

下列哪種說法是正确的:

A: 兩種指派的方式是一樣的

B: 推薦a的指派方式

C: 推薦b的指派方式

先公布答案:C

上面源代碼輸出的效果如下

0.1000000000000000055511151231257827021181583404541015625

顯然b是我們想要的效果

java.math.BigDecimal#BigDecimal(java.lang.String)

人家都怕你不仔細看給了你那麼多示例,還專門給了一個note

此構造函數是float或double轉到BigDecimal的推薦方式,因為該構造方法不會像BigDecimal(double)一樣會有一些不可預測的情況。

它最終調用了java.math.BigDecimal#BigDecimal(char[], int, int) 感興趣大家可以自己去看。

我們再看另外一個構造函數

java.math.BigDecimal#BigDecimal(double)

專門提到

這是因為double類型無法精确表示0.1。是以傳入0.1參數到該構造方法其實并不精确等于0.1。

更推薦使用參數為String的構造方法,換句話說用BigDecimal("0.1")來構造完全等于0.1的BigDecimal。 是以,推薦帶String參數的構造方法。

如果必須把double作為構造方法的參數時,注意和new BigDecimal(Double.toString(0.1d))的結果是完全不同的。

是以答案就不言而喻了。

計算機通過二進制來存儲資料,雙精度8位元組(64位)的表示

誰是代碼界3%的王者?- 第四題BigDecimal問題簡單解讀

其中第63索引位,共1位,表示符号位(sign bit),用s表示;0表示正數,1表示負數

第52到62索引位,共11位,表示指數(signed exponent),用e表示;2的多少次方

第51到0索引位(significant/mantissa value),共52位,表示小數部分,用m表示;有效位

浮點型:https://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html

十進制無法表示三分之一,二進制無法表示十分之一。

像三分之一一樣,三分之一無法用有限個十進制數表示。10的-1次幂(0.1)不是有限個2的幂的和,是以不能用有限個2進制位表示,而double是8位元組的,隻有64位,是有限個二進制數,是以無法精确表示0.1。

正如前面的幾個問題解答中我提到的幾個常見方法一樣,這類問題我們最好的辦法是看源碼!看源碼的注釋!!

看官方文檔!!看權威規範!!(如本文提到的《IEEE Arithmetic》的網頁)。

另外一個啟發是計算機專業基礎要紮實!!!二進制要了解的透徹一些。

開發的時候盡量多去源碼裡看注釋!!!

附錄

《誰是代碼界3%的王者?- 第三題switch問題簡單解讀》

《誰是代碼界3%的王者?- 第五題Lock的簡單解讀》