第一篇博文,寫個簡單的但是有點意思的——C語言中浮點數以整型輸出會得到什么?


 

 https://zhidao.baidu.com/question/1801972543144214347

這是百度知道上的一個問題,鏈接在上面。問的是C語言中printf("%d, 4+4.2");為什么不是輸出8?

剛看到這個問題的時候有點懵,總感覺應該是輸出8。我是這樣分析的:4+4.2結果是8.2,這是個double類型,然后以“%d”格式化輸出時自動轉換成整型也就是8。所以應該就是8啊。然后自己寫了段代碼測試了一下,結果。。。。。。。被打臉了。輸出是這樣的:

這個結果是怎么得到的?為什么8.2按%d的格式輸出會得到一個這么數字?

仔細想了一下,應該和浮點數的存儲方式有關。整型是以二進制補碼的形式存儲的,可以精確表示,存儲的就是數值。但是浮點數不一樣,浮點數是以編碼的形式存儲的,不是直接存儲數值,而且有精度問題,浮點數是以“符號位+階碼+尾數”的形式存儲。float類型符號位占1位,階碼占8位,尾數占23位,總共32位;double類型符號位占1位,階碼占11位,尾數占52位。所以說,如果printf在輸出時,因為格式字符是“%d”,所以它會以整型的方式去解析浮點數的編碼。將浮點數編碼直接當做二進制補碼來計算數值,就會出現上面的結果。

     既然確定了思路,那就朝這個方向來分析。首先將8.2以二進制編碼表示出來:0 000 1000 0010 000 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0第1個”0“表示符號,在這里是正數。接下來的11位表示階碼,這里表示130(3+127)。后面的52位表示尾數。在這里我犯了一個錯誤,因為系統和編譯器都是64位的,所以我以為int和double一樣,也是占64位。所以如果double以整型輸出,就是上面的二進制形式以整數補碼形式,轉換成10進制是1717986918嗎?很遺憾,並不是,而是:585580541548848742

    這個值遠比輸出的要大的多。開始我以為是我手動計算的8.2的編碼不對,又計算了幾遍之后發現還是一樣,而且專門去找了一個驗證程序(可以輸出變量值的二進制形式的一段代碼)驗證也沒問題。那么問題在哪呢?然后意識到可能是int和double所占的位數不一樣。用程序驗證一下果然如此:

  

   由上圖可知:int和float占4個字節即32位,double占8個字節即64位。如果double以int類型輸出的話,會產生截斷,只取低32位輸出,即輸出的是“011 0011 0011 0011 0011 0011 0011 0011 0”的值。這個二進制表示的值轉換成十進制就是1717986918


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM