轉載自:http://www.cnblogs.com/xkfz007/archive/2012/05/18/2508265.html
printf("%f",10/3);的結果是什麼?
今天在網上看到這個問題,自以爲的輸出是3.0,但是實際去跑一下,可以發現結果是0.0000
這一句雖然不長,但是其中蘊涵的知識點是很多的。
第一,10/3的結果是什麼?
這個很顯然結果應該是3
第二,printf語句格式化輸出的使用
%f就是要輸出浮點數,但是我們也發現給的參數其實是個整型數。所以也就出現了上面的結果。
第三,printf的原理是什麼?
這兒就牽扯到C中的不定參數的使用方法。具體可見這兒
簡單來說就是,printf從棧中取參數的時候是根據格式化語句中要求進行取數的。
這兒是%f,而浮點數是4個字節(32位操作系統),所以,要從棧中取4個字節,並且是按“浮點數的方式”。
正好,參數3是個整型數,整型數int也是4個字節,正好將整型數3取出。
第四,浮點數的存儲方式。
其實這是這個問題的關鍵所在。雖然整型int和浮點數float都是4個字節,但是他們對32位的使用方式是不一樣的。
整型數很簡單就是我們平常的方式,但是浮點數就不一樣的了。關於浮點數的存儲方式,網上有很多介紹。可以見這兒
簡單來說就是,對於32位,float是這樣分配的:0~22位是尾數,23~30是指數,最後一位是符號
類似如下:
知道了這個以後我們就可以分析出現上面結果的具體原由了。
整型數3在內存存儲如下:
0000 0000 0000 0000 0000 0000 0000 0011
但是現在我們要用浮點數的方式來解析這32位數字。
按照浮點數方式:
上面紅色是符號爲0,表示正數
藍色的是指數位,結果爲0,但是這兒要注意的一點是指數在存儲的時候是進行過偏移的,所以這兒要剪掉127,所以指數爲-127
最後的紫色是尾數,結果是2^(-22)+2^(-23),但是也要注意一點是,尾數在進行存儲的時候是歸一化過的,小數點前面其實有個1,所以最後尾數是1+2^(-22)+2^(-23)
所以最後的浮點數是:
轉化爲可讀數字就是5.87747385606e-39 ,這個數就非常小了,所以顯示的時候就是0.000000啦。
下面再考慮一個問題,真正的3.0怎麼存儲的?
如果看過關於浮點數存儲的上面那篇文章的話,應該就明白了,其實很簡單。
先把3.0轉化爲二進制是11.0,
然後歸一化後就是1.1000*2^1,這樣的話尾數是0.10000,指數是1,同時,指數在存儲時要進行偏移,所以要存127+1=128
所以,結果就是
將上面的數按整型數進行分析的話就是:0x40400000,十進制就是1077936128
下面是一個驗證的程序:
int main(){
float f;
int a;
int b;
a=3;
f=3.0f;
b=*(int*)&f;
printf("For integer a=3:\n");
printf("hex:%#x\n",a);
printf("int:%d\n",a);
printf("float:%f\n",a);
printf("For float f=3.0:\n");
printf("hex:%#x\n",b);
printf("int:%d\n",b);
printf("float:%f\n",f);
return 0;
}
結果如下: