printf("%f",10/3);的結果是什麼?

轉載自: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位數字。

按照浮點數方式:

0000 0000 0000 0000 0000 0000 0000 0011

上面紅色是符號爲0,表示正數

藍色的是指數位,結果爲0,但是這兒要注意的一點是指數在存儲的時候是進行過偏移的,所以這兒要剪掉127,所以指數爲-127

最後的紫色是尾數,結果是2^(-22)+2^(-23),但是也要注意一點是,尾數在進行存儲的時候是歸一化過的,小數點前面其實有個1,所以最後尾數是1+2^(-22)+2^(-23)

所以最後的浮點數是:

[1+2^(-22)+2^(-23)]*2^(-127)

轉化爲可讀數字就是5.87747385606e-39 ,這個數就非常小了,所以顯示的時候就是0.000000啦。

下面考慮一個問題,真正的3.0怎麼存儲的?

如果看過關於浮點數存儲的上面那篇文章的話,應該就明白了,其實很簡單。

先把3.0轉化爲二進制是11.0,

然後歸一化後就是1.1000*2^1,這樣的話尾數是0.10000,指數是1,同時,指數在存儲時要進行偏移,所以要存127+1=128

所以,結果就是

 

0100 0000 0100 0000 0000 0000 0000 0000

將上面的數按整型數進行分析的話就是:0x40400000,十進制就是1077936128 

下面是一個驗證的程序:

複製代碼
#include<stdio.h>

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;
}
複製代碼

 

結果如下:

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章