人逢喜事精神爽,總算熬到下班撩~~
正準備和同事打個招呼回家,被同事拖住問了.
🙋♂️: 大家組作的那塊代碼,把double類型數據成float有問題啊💨.
💁♀️: 嗯?不對是正常啊,float精度是沒有double高,但float能保存到小數點後好多位,對咱們來講徹底夠用了!
🙋♂️: 不是啊,這不是小數點多少位的問題,而是如今整型數據,轉出來也有問題啊,你看.html
💁♀️: XX00😱.... 這什麼鬼?工具
看到這個結果,差點閃到個人老腰🤦,咋不按套路出牌呢?
而後,下班路上,感受我好像被我摯愛的.Net欺騙了💔,double強轉float用了這麼多年,咋說不對就不對了?.Net不靠譜啊!.net
固然,我心裏仍是相信.Net是清白的,因此刨根究底,網上找的資料大可能是說這種強轉會照成小數點後的精度的問題,但是形成整數位的問題精度問題卻少有人說起.
爲了理解這個問題,咱們要從一些大學計算機基礎的相關知識講起😂.code
固然了,這都是廢話🤷, 重點是下面這條.htm
單精度浮點數
,double是雙精度浮點數
.根據國際標準IEEE 754,任意一個二進制浮點數V能夠表示成下面的形式:blog
(-1)^s表示符號位,當s=0,V爲正數;當s=1,V爲負數。內存
M表示有效數字,大於等於1,小於2。get
2^E表示指數位。class
舉例來講,十進制的5.0,寫成二進制是101.0,至關於1.01×2^2。那麼,按照上面V的格式,能夠得出s=0,M=1.01,E=2。基礎
十進制的-5.0,寫成二進制是-101.0,至關於-1.01×2^2。那麼,s=1,M=1.01,E=2。
對於32位的單精度
浮點數,最高的1位是符號位s,接着的8位是指數E,剩下的23位爲有效數字M。
對於64位的雙精度
浮點數,最高的1位是符號位S,接着的11位是指數E,剩下的52位爲有效數字M。
通過上面關於浮點數的介紹,相信你可能仍是一頭霧水,就像下面這幅漫畫展現的那樣🐎.
爲了不產生上面那種畫馬的跳躍,咱們一小步一小步,看看浮點數據具體怎麼在內存中存儲的.雙精度與單精度相似,這裏我以單精度爲例.
咱們先用上述步驟嘗試把9.0轉化成二進制存儲形式.
咱們能夠經過這個地址校驗計算結果的正確性. https://www.h-schmidt.net/FloatConverter/IEEE754.html
能夠看到,與咱們的計算結果徹底一致.
如今咱們用上面的步驟,把照成翻車的83459338轉成內存存儲形式看看.
經過在線工具轉換後證明咱們的轉換徹底正確.
而後咱們再把數據轉回來.
S是第31位,爲0, E =0011001
(25)+1=26, 重點在M,它是1.(有效數字位
)即 1.00111110010111110100001
1.00111110010111110100001
乘上2的26次方,爲100111110010111110100001000
,將其轉換爲十進制,爲 83459336
沒錯,就是83459336
,而不是83459338
🌋
83459338=> 100111110010111110100001010
83459336=> 100111110010111110100001000
能夠看到,兩個數字轉成成二進制後,倒數第二位產生了差別,而產生這種的差別的緣由就是單精度浮點數小數位23位不足以存儲全部二進制數(26位). 🚑這場事故告訴咱們,強轉雖好,容易翻車.