各位博客朋友大家好,相信有很多小伙伴在剛接觸數據類型的時候,都會糾結浮點數據是如何在內存中存儲,現在我們一起去探討這個問題?如果覺得有什么錯誤,歡迎各位小伙伴指出,好了,開始吧!!!
對於浮點類型數據,首先我們需要明白一點就是:浮點數和整數的編碼方式是差異甚大的
是嗎?我們舉個例子
#include <stdio.h>
int main()
{
int a = 9;
float *pFloat = (float *)&a;
printf("%f\n",*pFloat);
float b = 9.0;
float *p = &b;
printf("%f\n",*p);
return 0;
}
運行結果:
從以上結果得知浮點數的存儲方式和整數是不一樣的。
那么,浮點數據是如何存儲的呢?
根據國際標准IEEE(電子與電氣工程協會)規定,任何浮點數的二進制數存儲都要遵循以下公式進行轉換:
NUM = (-1) ^ s * M * 2 ^ E
來來來我們解釋一下:
S : 當S為1時,表示為負浮點數,當S為0時,表示正浮點數
M: 表示有效數 ,1<=M<2
2^E: 表示指數
相信有同學看到上面的公式已經心情開始浮躁了,我自己當初也是和你們一樣,心浮氣躁,嗯,這不對的,這得改,所以同學們,我們要耐得住寂寞,讓我們保持着
平靜的心態繼續往下探索吧!!!!
首先了解一下浮點在內存的存儲方式,請看圖~~
那問題來了,s表示符號位,0為正數,1為負數,那好辦,這個位要么0,要么1,當然負數的存儲方式是不一樣的,我們本章節討論的是正浮點的情況,浮點的存儲方式,所以s為0
那e是什么呢?這八位存儲的內容又是什么?
首先我們先確定e(指數域的二進制表示)是如何得來的,計算的e的結果需要用以下公式
e = E + Bias
E : 從上面公式知道E為指數
E的計算方式如下:
我們以135.5這個浮點數為標本
(1) 取整數135轉換為二進制(不知道自己用計算器或者百度)為10000111
(2) 取小數0.5轉換為二進制(方法為小數乘2取整數,不懂百度)為 0.5 * 2 = 1.0,所以小數位1,
舉個例子:如果小數是0.375,計算方式為
0.375 * 2 = 0.75 0
0 . 75 * 2 = 1.5 1
0.5 * 2 = 1.0 1
所以0.375轉換為二進制數值為 0.011 就是 011
(3)那么可以得出135.5的二進制為10000111.1
(4)將這個數值套進公式
10000111.1 = (-1)^0 * (1.00001111)*2 ^ 7
所以得出E的值為7
Bias : 是一個等於2^k-1 – 1的偏置值(k為指數域位數,對於32位浮點數是8,對於64位浮點數而言是11,因為我的是32位系統,所以k值為8),通過此方法可以得出Bias的值為
2^8-1 – 1 = 127
那么e = 7+127 = 134 轉換為二進制為 10000110
M : 小數部分 , 從上方可以得出結果為 00001111
好了,這樣就可以將 s , e , M
0 10000110 00001111 000000000000000
共32位.
所以得出結果,135.5在內存中的存儲方式如下
0000 0000 低地址 0
1000 0000 -128(最高位1為負數)
0000 0111 7
0100 0011 高地址 67
嗯,接下來驗證奇跡的時刻來了,寫個代碼測試以下
#include <stdio.h>
int main()
{
float m = 135.5;
char *a = (char *)&m;
printf("0x%p = %d\n",a,*a);
printf("0x%p = %d\n",a+1,*(a+1));
printf("0x%p = %d\n",a+2,*(a+2));
printf("0x%p = %d\n",a+3,*(a+3));
return 0;
}
運行結果如下
從結果可以得出我們的認證是正確的,哦,對了,還可以知道我這個系統是小端模式
最后附錄自己分析的鬼畫符~~~~~
本人 測試的操做系統為32位的ubuntu 14.04
好了這就是今天所有的內容,拜拜,有什么疑問或者建議的小朋友,記得請留言呦,讓我們一起進步。