基礎數據在內存中的存儲-C語言
假如數據10.101,對應各個位數 爲 ab.cde ,則轉換爲十進制的數據
a*2的1次方+ b*2的0次方+c*2的-1次方+d*2的-2次方 +e*2的-3次方
1*2(1)+0*2(0) + 1*2(-1)+0*2(-2)+1*2(-3)
整數:除2取餘,逆序排列,用2整除十進制數,得到 商 和餘數,然後在用2整除商,再得到商和餘數,循環進行,直到商爲0 ,最後把餘數逆序排列。
以下以10爲例
10(十進制)
商 餘數
10/2 5 0
5/2 2 1
2/2 1 0
1/2 0 1
1010(二進制)
小數 :乘2取整,順序排列,用2乘十進制小數,得到積,把整數部分取出,再用2乘餘下的小數部分,又得到一個積,再把積的整數部分取出,循環進行,直到積中的小數部分爲零,或者達到要求的精度,最後把整數部分順序排列
例1
0.125(十進制)
--------------------------------
積 整數部分
0.125*2 0.25 0
0.25*2 0.5 0
0.5*2 1.0 1
0.001(二進制)
例2
0.11(十進制)
--------------------------------
0.11 *2 0.22 0
0.22*2 0.44 0
0.44*2 0.88 0
0.88*2 1.76 1
0.76*2 1.52 1
0.52*2 1.04 1
0.04*2 0.08 0
。。。。。。。
無窮盡,如果要用32個二進制位存儲這個數據,只能捨棄低位,保留高位。
得到二進制數0.0001110...
對於這幾種類型的變量,都是用來存儲
整數數據,只不過因爲所佔內存大小不同而表示的數據的範圍不同。
看代碼的時候要分兩個層面:
(1)代碼層面,代碼根據語法是如何寫的。
(2)計算機層面,編譯器是如何翻譯的。
比如 char 類型,有的人說它是字符類型,存儲的是字符,這個理解是不全面的。
char a = 1; char 佔1個字節可以表示數據 0-255,當然可以存儲整數數據1.
char a = '1'; 單引號括起來的是字符數據,這是我們人類理解的概念,人在寫代碼的時候是能看明白的,但是計算機不明白,這就要用編譯器來給它翻譯過來,最終計算機存儲的是 字符'1' 的ascii碼,其實這個ascii碼也是個整數數據。
最終 整數數據 都轉化成二進制存儲到了計算機中,並且用的是補碼。
如果只有 大於0的數和加法,那麼就不需要補碼這個東西。
(1)計算機硬件支持加法 ,如果要支持減法要額外硬件電路,但是減法可以用加法加上一個負數來代替,所以按照這個思路就省了這部分硬件。
(2)模的概念
a 如果一個數據的範圍是 0-9,那麼就是有10個有效狀態,10就是這個數據的模
b 在模的概念下 假定模 是M , X+Y = M ,我們說X與Y 互補。
c 兩個互補的數在模的概念下 可以互爲 負數 :比如
時鐘 一圈的數字 是 0-11,它的模是12, 那麼如果我現在在0初去轉錶針,想轉到3的位置,則
我可以是正轉 3下,也可以反轉9下,所以在模爲12的這個系統下,可以用3代表-9。
(3)對於一個字節的char 變量來說 ,佔8bit ,可以表示256個狀態,表示非負數 0-255,模爲256.
當數據爲 1111 1111 時,再+1 則得到的數據 爲 1 0000 0000,最終會捨棄最高位的1,保留0000 0000,這樣一圈又迴歸到0了。
如果要表示負數,則一分未二,128個負數,128個非負數,最高位爲符號位,當爲1時,表示負數,0時表示非負數。
(1)非負數補碼 = 原碼
(2)負數補碼 = 反碼+1,計算規則是,符號位不變,其他位按位取反,最後這個數據+1
比如 -1 如下算法
0000 0001 正1
1000 0001 如果是負數,則符號位爲1
1111 1110 符號位不變,其他位按位取反
1111 1111 再+1 得到-1的補碼。
如下計算:
1-1 --》 1+(-1) --》0000 0001 + 1111 1111 = 1 0000 0000 溢出,捨棄最高位,是不是又迴歸0了?
(3)1000 0000 表示的數字是多少?
1000 0000 表示的數字 是 -128,而不是 -0;
-----------------------------------------------
假定有 -0這個數,則在內存中
1000 0000
1111 1111 符號位不變,其他取反
10000 0000 再加1溢出,捨棄最高位,內存中依然是 0000 0000;
-----------------------------------------------
-128的補碼是按照以下方法算的,因爲一個字節最高位是符號位,沒法表示128,所以算的的時候又借了一個字節
1000 0000 1000 0000 在16位中-128原碼
1111 1111 0111 1111 取反
1111 1111 1000 0000 +1得出16位中-128的補碼,存到1字節中,捨棄高位,爲 1000 0000
float 和 double 數據在內存中的存儲方式相同,只不過由於所佔字節大小不同而導致數值範圍和精度不同。
以下以float數據爲例,4個字節按照如下分配:
(1)科學計數法
對於 十進制數 223.456,換算成科學計數法 2.23456 * 10的2次方
對於二進制小數 1101.111 換算成科學計數法 爲 1.10111 * 2的3次方
(2)在計算機內部,float數的存儲,先換算成二進制的 科學計數法形式,然後分別把 尾數和指數部分存儲到內存中。
比如 1.10111*2的3次方,則在 8位指數位中要存儲 3 ,23位尾數位要存儲 110111。
對於二進制數來說,最高位永遠是1 所以最高位1就省略了,23位二進制位其實表示了24位尾數,所以存的是10111,
由於指數部分有正負 ,範圍是-127--128,在這裏按照移位存儲,3+127 ,所以存儲的是127+3
對於1101.111在內存中存儲的是如下:
(3)對於以下代碼
float a = 0.125;
float b = 0.123;
根據十進制轉化爲二進制的算法,a是有窮的,並且在23位尾數中可以完全存儲,所有內存中存的就是0.125;
對於b來說,轉化的二進制數是無窮的,當把尾數放到23位二進制位存儲的時候必然要捨棄低位數據,所以這裏的存儲肯定是不準確的。
-------------------------------------------------------------------------------------
所以對於一個 int a_int 來說,可以寫出 if(a_int == 2)這樣的表達式。
對於 float a_float 來說,不能寫這樣的if(a_float == 1.2)這樣的表達式。
同樣swtich語句可以switch(a_int),而不能switch(a_float)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.