計算機概論-資料儲存
講完了數字系統,這一篇是講關於資料儲存,我挑了數字來講,其他的我覺得書本看過去就好。
在電腦裡面的資料
位元(bit)是電腦儲存資料的最小單位,數值為0或1
每八個位元為一個位元組(byte)
儲存數字
整數
無號整數
無號整數是大於等於零的整數,範圍是零到無限大
但是電腦的儲存空間有限,所以數字會有表達範圍
假如電腦能儲存的空間有n位元,那就表示電腦能表達的最大數字為 $ 2^n-1 $
那麼在電腦中是如何儲存n位元的無號整數的呢
- 將數字轉為二進位
- 如果不滿n位元,則在前面補零
例如:將7儲存為8位元的無號整數
- 轉為二進位為 $ (111)_2 $
- 在前面補零到八個位元為止 $ (00000111)_2 $
如果將兩個整數相加但相加結果超出n位元的表達範圍(邊界),稱之為overflow
例如在8位元下
$ (11111111)_2+(00000001)_2 $ 應該等於 $ (100000000)_2 $
但是空間只有8位元的情況下
第九個位元會被捨去
就會使結果變成 $ (00000000)_2 $
有號整數(sign-and-magnitude)
那怎麼表達正負號呢
於是就定義了最前面(最左邊)的位元來表示正負號
0表示正號,1表示負號
雖然在n位元下,能表達的數字範圍少了一半,但總算能表達正負號了
例1:28存為8位元有號整數時
- 先轉為二進位 $ (11100)_2 $
- 補零補到七位元 $ (0011100)_2 $
- 視正負號補上第八位元 $ (00011100)_2 $
例2:-28存為8位元有號整數時
- 先轉為二進位 $ (11100)_2 $
- 補零補到七位元 $ (0011100)_2 $
- 視正負號補上第八位元 $ (10011100)_2 $
在這邊overflow仍然是存在的
注意:這種做法會有正零跟負零喔出現喔
二補數
雖然解決了表達正負號的問題,但電路上的實作卻遇到一個問題
加法跟減法需要分開實作,於是就有人想了,能不能兼具實作方便又能表達正負數
於是就有了二補數,做法為:
- 將數字做一補數
- 將數字加1
何謂一補數呢?只要將原數字的二進位反轉就是一補數了
例如8位元下, $ (00000101)_2 $ 的一補數是 $ (11111010)_2 $
而 $ (5)_{10} = (00000101)_2 $ 的二補數就是 $ (11111010)_2 $ 再加1,變成 $ (-5)_{10} = (11111011)_2 $
到底為什麼二補數可以讓減法用加法解決呢
例如 $ 1-1=0 $,我們可以將減法當作加上一個負值,變成 $ 1+(-1)=0 $
來檢驗一下這條算式是不是對的
1為 $ (00000001)_2 $,-1為 $ (11111111)_2 $
兩個相加等於 $ (100000000)_2 $,但是第九個位元會被捨去
所以就變成了 $ (00000000)_2 $
又例如 $ 5-4=5+(-4)=(00000101)_2+(11111100)_2=(100000001)_2 $
去掉第九位元之後就變成 $ (00000001)_2=(1)_{10} $
浮點數
正規化與IEEE標準
在儲存浮點數前,要先將二進位數字化為適當的科學記號,也就是正規化,然後按照IEEE訂的標準儲存
正規化就是將數字轉為 $ 1.xxxxx*2^{exp} $ 的形式
例如 $ (0.000000101001)_2 $ 要化為 $ 1.01001*2^7 $
然後我們可以得到三個部分
- Sign (正負號)
- Exponent (指數)
- Mantissa (尾數)
舉 $ 1.01001*2^7 $ 為例,Sign就是+,Exponent為7,Mantissa為01001
取出這三個部分後,就可以按照IEEE標準儲存浮點數了
IEEE規定32位元浮點數的Sign為1位元,Exponent為8位元,Mantissa為23位元
64位元浮點數的Sign為1位元,Exponent為11位元,Mantissa為52位元
其中Exponent不是用二補數儲存,而是採用無號整數
負數均位移 $ 2^{Exponent-1}-1 $,也就是加 $ 2^{Exponent-1}-1 $
例如1位移之後變128,-1位移之後變126
儲存浮點數的步驟:
- 確認正負號 (0 or 1)
- 將數字轉成二進位
- 正規化
- 找出Exponent與Mantissa
- 將結果連接起來
例如-0.0234375:
- 確認正負號:1
- 將數字轉為二進位:$ (0.0000011)_2 $
- 正規化:$ (1.1)_2*2^{-6} $
- 找出Exponent與Mantissa:$ E=-6+127=121=(01111001)_2 $ 且 $ M=(1)_2 $
- 將結果連接起來:$ \overbrace{1}^{Sign}\overbrace{01111001}^{Exponent}\overbrace{10000000000000000000000}^{Mantissa} $
有一個特別情況是數字為0的時候
不是00111111100000000000000000000000
也不是10111111100000000000000000000000喔XD
IEEE有特別規定所有位元為0的時候表示數字為0
overflow and underflow
overflow之前就談過了
如果你試圖存取超過 $ \pm(1.11111111111111111111111)_2*2^{128} $ 的數字
記憶體就會炸裂給你看www
underflow是指試圖存取比範圍更小的數字
也就是 $ \pm(0.00000000000000000000001)_2*2^{-127} $
截斷誤差
如果你試圖將一個極大一個極小的數字相加就會產生截斷誤差
例如 $ (11111111111111111111.11)_2+(0.00000000000000000000001)_2 $
結果應該是 $ (11111111111111111111.11000000000000000000001)_2 $
正規化後變成 $ (1.111111111111111111111000000000000000000001)_2*2^{19} $
但是在儲存的時候,尾數只有23位元
也就是11111111111111111111100會被儲存,最後的1卻不見了
所以在做浮點數運算的時候要非常小心