c語言單精度和雙精度存儲方式以及移位存儲的優(yōu)點

存儲方式

方式 位數(shù) 標準 模式
float 32bit IEEE R32.24
float.png
double 64bit R64.53
double.png
  1. 符號位(Sign):0代表正,1代表為負;
  2. 指數(shù)位(Exponent):用于存儲科學(xué)計數(shù)法中的指數(shù)數(shù)據(jù),并且采用移位存儲;
  3. 尾數(shù)部分(Mantissa):尾數(shù)部分

R32.24和R64.53的存儲方式都是用科學(xué)計數(shù)法來存儲數(shù)據(jù)的
用二進制的科學(xué)計數(shù)法第一位都是1,可以將小數(shù)點前面的1省略,所以23bit的尾數(shù)部分,可以表示的精度卻變成了 24bit,道理就是在這里。

那24bit能精確到小數(shù)點后幾位呢,我們知道9的二進制表示為1001,所以4bit能精確十進制中的小數(shù)點后一位,24bit就能使float能精確到小數(shù)點后6位,而對于指數(shù)部分,因為指數(shù)可正可負,8位的指數(shù)位能表示的指數(shù)范圍就應(yīng)該為:-127-128了, 所以指數(shù)部分的存儲采用移位存儲,存儲的數(shù)據(jù)為元數(shù)據(jù)+127。

下面就看看8.25和120.5在內(nèi)存中真正的存儲方式:

8.25換算成二進制科學(xué)計數(shù)法

8 = 1000;
0.25 = 0.01;

8.25(10) = 1000.01(2) = 1.00001*2^3 

  
按照上面的存儲方式
符號位為   0,表示為正;
指數(shù)位為   3+127=130,
尾數(shù)部分為 00001 = 00001000000000000000000 //23位
故8.25的存儲方式如下:
0--10000010--00001000000000000000000  
即01000001000001000000000000000000 


#同理

120.5在內(nèi)存中的存儲格式如下 
0--10000101--11100010000000000000000

即01000010111100010000000000000000 
 

那么如果給出內(nèi)存中一段數(shù)據(jù),并且告訴你是單精度存儲的話,你如何知道該數(shù)據(jù)的十進制數(shù)值 呢?其實就是對上面的反推過程,比如給出如下內(nèi)存數(shù)據(jù):

01000001001000100000000000000000 
第一步:符號位為0,表示是正數(shù);  
第二步:指數(shù)位為10000010,換算成十進制為130,所以指數(shù)為130-127=3; 
第三步:尾數(shù)位為01000100000000000000000,換算成十進制為 (1+1/4+1/64);
#尾數(shù)部分都要+1  
十進制數(shù)值為:2^3*(1+1/4+1/64)=8+2+1/8=10.125

移位存儲的詳解

以32位單精度float內(nèi)存模型為例

float-struct.png

從上圖可以看出 指數(shù)部分8位存儲空間實際上并不在意同一個字節(jié)上,通常情況下8位存儲空間可以存儲的數(shù)值范圍為

0000000 0 ~ 1111111 1

也就是從0開始到 255結(jié)束,一共 256個數(shù)。

但是新組成的8位數(shù)是用來表示整串32位單精度浮點數(shù)的冪指數(shù)(階碼)的,而浮點數(shù)的冪指數(shù)(階碼)是有必要使用負數(shù)的。

既要表示正數(shù),又要表示負數(shù),因此我們要拿出一位來表示正負號,通常都是拿一個字串最左邊的那位即最高位來表示正負號的,使用傳統(tǒng)的方式,即一個字節(jié)的最高位(最左邊那位)為1時表示負數(shù),那么我們可以得到兩個區(qū)間,這里我們?yōu)榱丝粗奖氵€是使用空格來隔開最高位的符號位和最低位的那位特殊位:

第一個區(qū)間:

0 000000 0~ 0 111111 1

即+ 0 到 127,

第二個區(qū)間:

1 000000 0~ 1 111111 1

即 -0 到 - 127,

這里出現(xiàn)了2個0,一個正+0,一個-0

使用移位存儲方式會有什么效果呢? 移位存儲要+127 , 存儲示例:

127 使用這個新生成的字節(jié)來表示,則是:

0 111111 1 ,


如果我們要表示 0,則有 0+127=127 即 0 111111 1

:0 000000 0 + 0 111111 1= 0 111111 1


我們要表示1,則有 1+127=128 即 1 000000 0

:0 000000 1 + 0 111111 1= 1 000000 0

我們要表示 2,則有 2+127=129 即 1 000000 1

:0 000001 0 + 0 111111 1= 1 0000001

………………………………………………………………

我們要表示 128,則有 128+127=255 即 1 111111 1

:1 000000 0+ 0 111111 1= 1 111111 1

這個128是我們能夠使用 8位二進制移位存儲算法表示的最大的正數(shù)了,再大就溢出了。 同樣,我們來看看負數(shù):

我們要表示 -1時,則有( -1) +127=127-1=126 即 0 111111 0

:0 111111 1 - 0 000000 1= 0 111111 1

我們要表示 -2時,則有( -2)+ 127=127-2=125 即 0 111110 1

:0 111111 1 - 0 000001 0= 0 111110 1

……………………………………………………………………………………………… 我們要表示 -127時,則有(-127)+127=127-127=0 即 0 000000 0

:0 111111 1 - 0 111111 1= 0 000000 0

這-127,是我們能夠使用 8位二進制采用移位存儲所能表示的最小的負數(shù)了,再小就溢出。

由上面的 例子,我們可以得出規(guī)律,采用移位存儲技術(shù),我們可以使用 8位二進制來表示從 -127~128 共計:

127個負數(shù)+零(0)+128個正數(shù)=256個數(shù)

看來使用移位存儲即沒有+0和-0的問題,又充分的使用這個新生成的 8位二進制數(shù)來最大限度的表示單精度浮點數(shù)的冪指數(shù)(階碼),是非常合理的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容