先前在前文 《老大說:誰要再用double定義商品金額,就本身收拾東西走》 中就已經痛徹心扉地聊過:工具
在處理諸如 訂單交易、 貨幣計算、以及 商品金額慎用浮點數(double
/float
)去定義變量,不然可能會遇到各類奇葩的問題,具體示例在那篇文章中都詳細展現過。
當時寫那篇文章的時候,我覺得你們對於小數轉二進制的換算早已瞭然於胸,因此也就沒有給出具體的換算過程。結果文章發出來後,私信裏一票小夥伴反饋說,文中那些小數轉二進制的例子究竟是怎麼換算出來的,最好詳解一下。編碼
得嘞,這不就來了嘛!spa
順帶聊一句,看來《計組原理》或者說《計算機系統》這門課有必要小規模回爐重造一下了(滑稽)。3d
不過實不相瞞,CRUD、複製粘貼、調接口、寫業務代碼久了,計算機基礎確實好多都忘了...我也有深有同感!code
學過 《計算機組成原理》 或者相似 《計算機系統》 這些課程的小夥伴們應該都知道,浮點數在計算機中的存儲方式遵循IEEE 754 浮點數計數標準,能夠表示爲:blog
採用尾數 + 階碼的編碼方式,更通俗一點說,就是相似於數學課本上所學的科學計數法表示方式:有效數字 + 指數位!接口
所以,只要給出:符號(S)、階碼部分(E)、尾數部分(M) 這三個維度的信息,一個浮點數的表示就徹底肯定下來了,因此float
和double
這兩種類型的浮點數在計算機中的存儲結構就表示成下圖所示這個樣子:rem
一、符號部分(S)數學
0
-正 1
-負it
二、階碼部分(E)(指數部分):
float
型浮點數,指數部分8
位,考慮可正可負,所以能夠表示的指數範圍爲-127 ~ 128
double
型浮點數,指數部分11
位,考慮可正可負,所以能夠表示的指數範圍爲-1023 ~ 1024
三、尾數部分(M):
浮點數的精度是由尾數的位數來決定的:
float
型浮點數,尾數部分23
位,換算成十進制就是 2^23=8388608
,因此十進制精度只有6 ~ 7
位;double
型浮點數,尾數部分52
位,換算成十進制就是 2^52 = 4503599627370496
,因此十進制精度只有15 ~ 16
位因此,浮點數交給計算機存儲的時候,可能會有精度丟失問題!!!所以使用時須要格外當心,若是真由於這一塊出了bug,定位問題仍是很是艱難的,因此預防工做要作好。
上面說的是IEEE標準規定的內容,屬於理論規約。那一個小數到底要怎麼換算成二進制呢?咱們得拿實際例子來解釋。
好比:把十進制小數0.875
轉換成二進制,具體怎麼操做?
能夠分幾大步走:
一、以小數點爲界,拆分
二、整數部分轉換
整數轉二進制我想你們應該都熟悉,使用:除2取餘法 便可。而這裏的0.875
整數部分爲0,無需操做。
三、小數部分轉換
小數部分的轉換不一樣於整數部分,採用的是 「乘2取整法」 ,圖示一下就明白了:
四、合併結果
整數部分 + 小數部分
,最終獲得二進制結果爲0.111
。
因此該結果按照上一節所述的尾數 + 階碼的計算機計數方式,則能夠表示爲:
因此對應可得:
0
float
爲例,應爲 127 +(-1)= 126
,所以二進制表示爲:01111110
float
爲例,應爲23
位,所以尾部補齊後爲11000000000000000000000
。所以最終的總結果爲(以32
位精度float
表示):
00111111011000000000000000000000
再好比:把十進制小數6.36
轉換成二進制,具體怎麼操做?
但凡能用圖示,我就不想寫文字,因此用一張圖就能夠解釋得明明白白:
整數部分 + 小數部分,所以最終獲得的結果二進制結果爲110.01011100...
。
仍是按照上一節所述的尾數 + 階碼的計算機計數方式,則能夠表示爲:
因此對應可得:
float
爲例,應爲 127 +(2)= 129
,所以二進制表示爲:10000001
1001011100...
,其實它自己無限不循環,但若以float
型精度來截取23
位,則能夠表示爲10010111000010100011111
所以最終的總結果爲(以32
位精度float
表示):
01000000110010111000010100011111
因此像這種無限位數的尾數狀況,用計算機存儲產生截取是必然的,一定會有必定的精度損失!因此這也從根本上解釋了爲何float或者double這種類型數據使用時的風險性,所以必需要結合實際業務理性考量。
你們若是對上面的計算結果不放心,或者想檢查手動換算的結果是否正確,也有直接的這種二進制轉換工具站,典型的好比binaryconvert
不想手動換算的,直接去上面輸入,轉換一下便可獲得結果,並且能夠進制互換,使用很是方便。
有時候回顧一下基礎真的蠻有意思的,好比寫這篇文章時,雖然是很基礎的東西,可是表達出來的過程仍是挺有趣的,尤爲是畫圖展示的過程,但願能和小夥伴們共勉。