浮點型的記憶體表示級資料型別轉化

2021-09-25 20:17:04 字數 4133 閱讀 5552

資料型別轉化

c/c++

type

lenbool

1byte

char

1byte

short

1byte

int4byte

long

4byte

float

4byte

double

8byte

乙個位元組有8位 28=256

整數7用二進位制表示為

0000 0111

+ ?||

0000 0000

為了簡單的使7 + (-7) = 0, -7 二進位制表示為 1111 1001。也就是我們經常說的負數的二進位制表示為正數的反碼加1。

推導過程

0000 0000 0000 1111 (15)

1111 1111 1111 0000 (15的反碼)

1111 1111 1111 1111 (加上1就可以導致資料溢位,8位清零)

0000 0000 0000 0001 (-15 表示為 1111 1111 1111 0001)

0000 0000 0000 0000 (0)

ansi/ieeestd 754-1985標準

ieee 754是最廣泛使用的二進位制浮點數算術標準,被許多cpu與浮點運算器所採用。ieee754規定了多種表示浮點數值的方式,在本文件裡只介紹32bits的float浮點型別。它被分為3個部分,分別是符號位s(sign bit)、指數偏差e(exponent bias)和小數部分f(fraction)。

其中s位佔1bit,為bit31。s位為0代表浮點數是正數,s位為1代表浮點數是負數,比如說0x449a522c的s位為0,表示這是乙個正數,0x849a522c的s位為1,表示這是乙個負數。

e位佔8bits,為bit23~bit30。e位代表2的n次方,但需要減去127,比如說e位為87,那麼e位的值為2(87-127)=9.094947017729282379150390625e-13。

f位佔23bits,為bit0-bit22。f位是小數點後面的位數,其中bit22是2-1=0.5,bit21是2-2=0.25,以此類推,bit0為2-23=0.00000011920928955078125。但f位里隱藏了乙個1,也就是說f位所表示的值是1+(f位bit22~bit0所表示的數值),比如說f位是0b10100000000000000000001,只有bit22、bit20和bit0為1,那麼f位的值為1+(2-1+2-3+2-23),為1.62500011920928955078125。

綜上所述,從二進位制數換算到浮點數的公式為:(-1)s×2e-127×1.f

舉個換算的例子:

下面來看看浮點數與二進位制數如何轉換。

二進位制數換算成浮點數:

假如在記憶體中有乙個二進位制數為0x449a522c,先將十六進製制轉換成二進位制,如下:

0100 0100 1001 1010 0101 0010 0010 1100

按照sef的格式分段,如下:

0 10001001 00110100101001000101100

這個數值不是特殊的情形,可以按照公式(-1)s×2(e-127)×(1+f)轉換。s位的值為(-1)0=1,e位的值為2137-127=1024。f位的值為1+2-3+2-4+2-6+2-9+2-11+2-14+2-18+2-20+2-21= 1.205632686614990234375。最終結果為1×1024×1.205632686614990234375=1234.56787109375。

其中f位比較長,使用二進位制方式轉換比較麻煩,也可以先轉換成十六進製制再計算,轉換為十六進製制如下:

0011 0100 1010 0100 0101 1000

0x3 0x4 0xa 0x4 0x5 0x8

f位為23bits,需要在最後補乙個0湊成24bits,共6個十六進製制數。f位的值為1+3×16-1+4×16-2+10×16-3+4×16-4+5×16-5+8×16-6=1.205632686614990234375,與上面使用二進位制方法得到的結果相同。

char ch =

'a';

short s = ch;

printf

("s is %d\n"

, s)

;

程式列印結果:

s is 65
從記憶體的角度分析,char型資料佔乙個位元組,short佔兩個位元組,把ch 賦值給s,ch的8位複製到s低8位,s的高8位為0,表示為 0000 0000 0100 0001。

short sh =

512;

char ch1 = sh;

printf

("ch1 = %d\n"

, ch1)

;

程式列印結果為:

ch1 =

0

從記憶體角度分析,short佔2個位元組 也就是16byte,0010 0000 0000,char佔乙個位元組8byte, 將short型的sh賦值給char型ch1,實際上賦值的是sh的低8位 0000 0000。所以ch1 的列印結果為0。

int t =

1782579

;short s1 = i;

printf

("s1 = %d\n"

, s1)

;

程式執行結果:

s1 =

2097

從記憶體的角度分析,int型的i賦值給short型的s1,實際上是將t的低16位複製給s1。

41

short ss =-1

;42int ii = ss;

43printf

("ii = %d\n"

, ii)

;

程式執行結果:

ii =

-1

從記憶體角度分析,ss 為1111 1111 1111 1111,將ss 賦值給ii,將16位複製到ii的低16位,然後進行符號擴充套件, ii 為 1111 1111 1111 1111 1111 1111 1111 1111。

45

int a =5;

46float f = a;

47printf

("f = %f \n"

, f)

;

程式執行結果:

f =

5.000000

為什麼是5.0, 實際上int 5被翻譯成1.25 * 22, 套用公式「(-1)s * 1.***x * 2exp-127」可以得出 s=0,***x=0.25, exp = 129, 根據這些值可以畫出float f的記憶體結構圖 0 1000 0001 0100 000 …0 。

再看乙個例子:

49

int b =37;

50float c =*(

float*)

&b;51

printf

("c = %f\n"

, c)

;

程式執行結果:

c =

0.000000

為什麼會是0呢?作業系統將指向(int *)的位址認為是指向(float * ),所以對於b所指向的四個位元組的空間會按float型別翻譯,32 剛好位於 f區域,翻譯成float型資料會是乙個很小的資料。

53

float d =

7.0;

54short e =*(

short*)

&d;55

printf

("e = %hd\n"

, e)

;

程式執行結果:

e =

0

浮點型資料型別

double 和 float 資料型別都是浮點型,在從記憶體中取出來後,即便之前的賦值是個 整型的資料型別,把浮點型取出來後都會變成實數的小數,比如賦值為0,取出來後就是0.0了 float var f 0 double var d 0 system.out.println var f 0.0 sy...

基本資料型別 浮點型 指標

浮點數家族包括float double和long double型別。通常,這些型別分別提供單精度 雙精度以及在某些支援擴充套件精度的機器上提供擴充套件精度。ansi標準僅僅規定long double至少和double 一樣長,而double至少和float一樣長。標準同時規定了乙個最小範圍 所有浮點...

MATLAB的資料型別整型和浮點型

可以看出matlab的數值型別跟c語言一樣分為整型和浮點型,但是需要特別注意的是,它的用意和c語言完全不一樣。前者的整型資料主要為影象處理等特殊的應用問題提供資料型別,而對於一般數值運算,絕大多數是採用雙精度浮點型的資料。8種整數型別 整數型別 數值型別 轉換函式 有符號8位 2 7 2 7 1 i...