提到“在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位)的表示

其中第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的簡單解讀》