文章目錄
常用數制
十進制(Decimal)
二進制(Binary)
十六進制(Hexadecimal)
計算機內部採用二進制。這是因爲二進制數只有0和1兩個數碼,採用晶體管的導通和截止、脈衝的高電平和低電平都很容易表示它。
計算機中如何表示數
比如 正數1 ,在java中是用int類型,佔四字節,所以在計算機中表示爲:
00000000 00000000 00000000 00000001
負數在計算機中不是用原碼錶示,而是用補碼錶示,比如 -1 ,在計算機中是:
11111111 11111111 11111111 11111111
計算方法見下文。
數制轉換
二進制和十進制的轉換
Binary——》Decimal :按權展開相加即可。
Decimal——》Binary :分爲整數部分和小數部分。
整數部分:除2取餘法
小數部分:乘2取整法
所以:
0.6879D≈0.1011B
任何十進制整數都可以精確轉換成一個二進制整數,但任何十進制小數卻不一定可以精確轉換成一個二進制小數。
十六進制和10進制的轉換
和 二進制與10進制的轉換類似。也可以將16進制先轉換成二進制轉換完成後,再轉換爲16進制。
十六進制和二進制的轉換
-
二進制數轉換成十六進制數可採用“四位合一位法。
[例2.5] 若要把1101111100011.10010100B轉換爲十六進制數,則有
所以,1101111100011.10010100B=1BE3.94H
-
16進制轉2進制,採用分解法。
例2.6] 若要把十六進制數3AB.7A5轉換爲一個二進制數,則有
原碼反碼和補碼
原碼,反碼,補碼的引入是爲了解決做減法的問題
原碼:
例如10進制的 2 原碼(用8位二進制表示):0000 0010
10進制的-2的原碼:1000 0010
原碼,雖然直觀易懂,易於正值轉換。但用來實現加減法的話,運算規則總歸是太複雜。例如:
1+ (-1) : 0000 0001 + 1000 0001= 1000 0010 ( -2)
結果顯然不正確,所以有了反碼。
反碼:
正數的反碼是自己本身
負數的反碼是除符號位的其他位,按位取反。
例如:2的反碼是 0000 0010 ,-2的反碼 1111 1101
用反碼計算:2+(-2)
0000 0010 + 1111 1101 = 1111 1111 (對結果取反:1000 0000 = -0)
如果是兩個負數相加:
-2 + (-2) = 1111 1101 + 1111 1101 = 1111 1010 (對結果取反:1000 0101 = -3)
結果好像有問題。
所以出現補碼,它利用用‘模’和‘同餘’的原理。我們可以看到其實減去一個數,對於數值有限制(比如用8位),有溢出的運算(模運算)來說,其實也相當於加上這個數的同餘數。
補碼:
正數的補碼等於原碼。負數的補碼等於其反碼加1
再來計算 -2 + (-2)
-2的反碼:1111 1101 加1 等於 1111 1110
所以:1111 1110 +1111 1110 = 1111 1100 (對結果再求補碼)
結果是 1000 0100 = -4
所以加法運算法則是:兩個數的補碼相加對結果求補碼。
數制運算
二進制的運算分爲二進制整數運算和二進制小數運算,運算法則完全相同。由於大部分計算機中數的表示方法均採用定點整數表示法。
擴展:對於定點小數的存儲,實際上,計算機不存儲小數點,但小數點的位置必須知道,不然計算機無法知道真實數值。計算機作何知道小數點的位置呢?那麼就需要有一個定點小數的規範。假設機器字長8 bits,我們規定從左至右,第一位爲符號位,接着後5位表示定點小數的整數部分,後兩位表示定點小數的小數部分。那麼26.510的實際存儲形式爲01101010。由於對定點小數並無統一的規範,且數值表示的範圍和精度有限,所以普通計算機對於小數的表示採用浮點數形式。
運算分爲兩類:
算數運算
加、減、乘、除
邏輯運算
與(&)、或(|)、非(~)、異或(^)
這裏重點說下 ~運算 ,經過(~)運算以後,也就是逐個取反
比如5的二進制: 0000 0000 0000 0101
5(~)運算後得到的:1111 1111 1111 1010,那麼這個二進制在計算機中保存的形式是這樣子的。如果將計算機內存中這個值讀取出來,則需要對齊取反加1(因爲符號位是1 ,是負數,是用補碼錶示的)。
java中有些代碼,爲了提高效率,並不讀取該值,而是直接做移位操作,然後更改值,這樣可以讀取一些狀態值,效率更高。比如java的ThreadPoolExecutor
中有這樣幾個定義:
//111
private static final int RUNNING = -1 << COUNT_BITS;
//000
private static final int SHUTDOWN = 0 << COUNT_BITS;
//001
private static final int STOP = 1 << COUNT_BITS;
//010
private static final int TIDYING = 2 << COUNT_BITS;
//011
private static final int TERMINATED = 3 << COUNT_BITS;
其中COUNT_BITS值是29,則通過移位,狀態值分別是 111 ,000, 001,010,011 分別取的高三位作爲狀態碼
特別是第一個111, 計算過程是,-1 在計算機中表示是
11111111 11111111 11111111 11111111
, 左移29位後就是
11100000 00000000 00000000 00000000
常見編碼
BCD碼(Binary Coded Decimal,十進制數的二進制編碼)和ASCII碼(American Standard Code for Information Interchange,美國信息交換標準碼)是計算機中兩種常用的二進制編碼.前者稱爲十進制數的二進制編碼,後者是對鍵盤上輸入字符的二進制編碼.
計算機對十進制數的處理過程是:鍵盤上輸入的十進制數字先被替換成一個個ASCII碼送入計算機,然後通過程序替換成BCD碼,並對BCD碼直接進行運算。也可以先把BCD碼替換成二進制碼進行運算,並把運算結果再變爲BCD碼,最後還要把BCD碼形式的輸出結果變換成ASCII碼才能在屏幕上加以顯示,這是因爲BCD碼形式的十進制數是不能直接在鍵盤/屏幕上輸入/輸出的.
BCD碼
1.BCD碼
BCD碼是一種具有十進制權的二進制編碼.BCD碼的種類較多,常用的有8421碼、2421碼、餘3碼和格雷碼等.現以8421碼爲例進行介紹.
8421碼也是BCD碼中的一種,因組成它的4位二進制數碼的權爲8、4、2、1而得名.8421碼是一種採用4位二進制數來代表十進制數碼的代碼系統,在這個代碼系統中,10組4位二進制數分別代表了0~9中的10個數字符號,
如
十進制數 | 8421碼 | 十進制數 | 8421碼 |
---|---|---|---|
0 | 0000B | 8 | 1000B |
1 | 0001B | 9 | 1001B |
2 | 0010B | 10 | 00010000B |
3 | 0011B | 11 | 00010001B |
4 | 0100B | 12 | 00010010B |
5 | 0101B | 13 | 00010011B |
6 | 0110B | 14 | 00010100B |
7 | 0111B | 15 | 00010101B |
BCD碼加法運算:
例: 已知X=48, Y=69,試分析BCD的加法過程.
解:根據BCD數的定義,如下豎式成立:
在進行BCD加法過程中,計算機對二進制加法結果進行修正的原則是:若和的低4位大於9或低4位向高4位發生了進位,則低4位加6修正;若高4位大於9或高4位的最高位發生進位,則高4位加6修正.這種修正由微處理器內部的十進制調整電路自動完成.
BCD碼減法運算:
在BCD減法過程中,計算機對二進制運算結果修正的原則是:若低4位大於9或低4位向高4位有借位,則低4位減6修正;若高4位大於9或高4位最高位有借位,則高4位減6修正.和BCD加法類似,這個修正也由機器內部的十進制調整電路自動完成.
ASCII碼
ASCII碼由7位二進制數碼構成,共可爲128個字符編碼,這128個字符共分兩類:一類是圖形字符,共96個;另一類是控制字符,共32個.ASCII碼共有7位,作爲一個字節還多出一位.多出的這位是最高位,常常用作奇偶校驗,故稱爲奇偶校驗位
漢字編碼
編碼 | 英文字節數 | 漢字字節數 |
---|---|---|
GB2312 | 1 | 2 |
GBK | 1 | 2 |
UTF-8 | 1 | 3 |
IOS-8859-1 | 1 | 1 |
UTF-16 | 2 | 2 |
校驗碼編碼和解碼
信息在傳輸過程中也會因爲傳輸線路上的各種干擾而使接收端接收到的數據和發送端發送的數據不相同.爲了確保計算機可靠工作,人們常常希望計算機能對從存儲器中讀出信息或從接收端接收到的信息自動做出判斷,並加以糾錯.由此,引出了計算機對校驗碼的編碼和解碼問題.
奇偶校驗碼
分爲奇校驗和偶校驗兩種。
編碼規律是要求編碼後的校驗碼(包括有效信息和奇偶校驗位)中“1”的個數爲奇數或偶數(對應奇校驗和偶校驗)。ASCII碼就採用了該校驗方式:其中低七位是有效信息位,最高位是校驗位。
奇偶檢驗電路通常採用異或電路實現,如果採用偶檢驗,發送端將所有信息位經過異或後所得的結果就是偶校驗位,若採用奇校驗,所有信息位異或後取反就是奇校驗位.接收端將接收到的全部信息(包括校驗信息位)進行異或運算。
例如,字符C的ASCII碼爲01000011B,採用偶校驗,校驗位形成過程爲:
校驗位=D6⊕D5⊕D4⊕D3⊕D2⊕D1⊕D0=1⊕0⊕0⊕0⊕0⊕1⊕1=1,校驗位佔D7位,最後形成含有偶檢驗位的信息編碼爲11000011.這樣,接收端奇偶校驗電路只要判斷每個字節中是否有偶數個“1”(包括奇偶校驗位)就可以知道信息在傳輸中是否出錯.
海明碼編碼
海明碼的碼位有(n+k)位,n爲有效信息的位數,k爲奇偶校驗位位數.k個奇偶校驗位有2^k種組合,除採用一種組合指示信息有無錯誤外,尚有(2k-1)種組合可以用來指示出錯的碼位.因此,若要能指示海明碼中任意一位是否有錯,則校驗碼的位數k必須滿足如下關係:
n與k的關係表:
k(最小) | n | k(最小) | n |
---|---|---|---|
2 | 1 | 5 | 12~26 |
3 | 2~4 | 6 | 27~57 |
4 | 5~11 | 7 | 58~120 |
在n和k的值確定以後,還要進一步確定哪些位爲有效信息位以及哪些位作爲奇偶校驗位.在海明碼編碼中規定:位號恰好等於2的權值的那些位(即:第1(20)位、第2(21)位、第4(2^2)位、第8(263)位……)均可用作奇偶校驗位,並命名爲P0, P1, P2, P3, …, Pk位.
校驗位和被校驗位的關係爲:
海明碼的位號可以看做:
例如信息位D6的海明碼位號爲3(20+21),信息位D2的海明碼位號爲9(20+23)
所以D3就被P0和P1校驗,D6就被P0和P3校驗。每個校驗位負責對應位的校驗。
奇偶校驗位 | 被校(海明碼)位號 |
---|---|
P0(1) | 3,5,7,9,11 |
P1(2) | 3,6,7,10,11 |
P2(4) | 5,7,6 |
P3(8) | 9,10,11 |
原理:
字符A的ASCII碼位41H(1000001B),填入海明碼的相位後爲:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|
P0 | P1 | 1 | P2 | 0 | 0 | 0 | P3 | 0 | 0 | 1 |
確定奇偶校驗位P0~P3的值必須按上一個表進行.方法是按偶校驗或奇檢驗規則統計相應被校海明碼位號中“1”的個數.對於偶校驗編碼的方法是:若被校位號中“1”的個數爲奇數,則相應奇偶校驗位爲“1”;若被校驗位號中“1”的個數爲偶數,則相應偶校驗位爲“0”.例如,P0的所校位號爲3、5、7、9、11(見表2.4),其中只有第3和第11位爲“l”(偶數個“1”),故P0=3⊕5⊕7⊕9⊕11=0。其他幾個校驗位按同樣方式計算。最終字符A用海明碼編碼結果爲:
00100001001B
海明碼的糾錯:
海明碼糾錯是在海明碼解碼過程中完成的.糾錯很簡單,只要把錯位取反即可。
海明碼的出錯指示碼
又稱爲指誤字.指誤字不僅可以指出數據在讀出或傳送過程中有無錯誤,而且可以指示究竟錯在哪一位上.例如,若E3E2E1E0=0000B,則表明數據在讀出或傳送過程中沒有發生錯誤;若E3E2E1E0=0001B,則表明海明碼的第1位(奇偶校驗位P0)有錯;若E3E2E1E0=0011B,則表明海明碼的第3位有錯…….
出錯標誌位的求取規則按下表對應的進行求取:
出錯標誌位 | 被檢海明碼的位號 |
---|---|
E0 | 1,3,5,7,9,11 |
E1 | 2,3,6,7,10,11 |
E2 | 4,5,6,7 |
E3 | 8,9,10,11 |
碼位號中“1”的個數爲奇數,則相應出錯標誌位的值爲“1”;若被檢測所有海明碼位號中“1”的個數爲偶數,則相應出錯標誌位的值爲“0”.例如,若接收端接收到的字符A的海明碼中第11位錯成“0”,變成如下形式:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
則有:E0 = 0⊕1⊕0⊕0⊕0⊕0 = 1 (判斷1,3,5,7,9,11位上1的個數是否爲偶數,是則取0,否則取1)做異或運算。
同理有:E1=1 ,E2=0,E3=1
故指誤字爲E3E2E1E0=1011B,指示第11位出錯.將它取反,則錯誤碼得到糾正.
CRC循環冗餘校驗碼
Cyclic Redundancy Check可以發現並糾正錯誤。
理解CRC的關鍵是理解模2運算。
模2加減:可用異或門實現,即:
0+0=0;0+1=1;1+0=1;1+1=0
0-0=0;0-1=1;1-0=1;1-1=0;
模2乘法:模2加求部分積之和.
1 0 1 1
X 1 0 1
---------------
1 0 1 1
0 0 0 0
1 0 1 1
---------------
1 0 0 1 1 1
模2除法:
用模2減求部分餘數,每上一位商,部分餘數要減少一位,上商規則是:餘數最高位爲1,就商1,否則商0.當部分餘數的位數小於除數時,該餘數爲最後餘數。例如計算 1100000 和1011做模2除。
最終商1110 餘數 010
1 1 1 0 //商
---------------
1 1 0 0 0 0 0 //被除數,注意首位爲1
1 0 1 1 //被除數首位爲1,除以除數
---------------
1 1 1 0 0 0 //餘數去除首位,作爲新的被除數
1 0 1 1 //被除數首位爲1,除以除數
---------------
1 0 1 0 0 //餘數去除首位,作爲新的被除數
1 0 1 1 //被除數首位爲1,除以除數
---------------
0 0 1 0 //餘數,此時餘數位數少於除數,不能繼續除了(忽略首位0)
設待編碼的有效信息以多項式M(x)表示,將M(x)左移r位得到多項式M(x)×xr,使低r位二進制位全爲零,以便與隨後得到的r位校驗位相拼接.那怎樣求得校驗位呢?方法是使用多項式M(x)×xr除以生成多項式G(x),求得的餘數即爲校驗位.爲了得到r位餘數(校驗位), G(x)必須是r+1位的.
假設M(x)×xr除以生成多項式G(x)所得的餘數用表達式R(x)表示,商的表達式用Q(x)表示,則它們之間的關係如下:
做一個恆等變形:
公式中的加法和乘法都是模2運算,兩個相同的數的模2和爲0 即R(x)+R(x)= 0
所以最終的CRC編碼爲:
可以看出,所求得的CRC碼是一個可被用G(x)表示的數碼除盡的數碼.
糾錯:
CRC碼傳輸到目標部件時,用約定的多項式G(x)對收到的CRC碼進行“模2除”,若餘數爲0,則表明該CRC校驗碼正確,否則表明有錯,不同的出錯位,其餘數是不同的.由余數指出是哪一位出了錯,然後加以糾正.
表2.6
由表2.6可見:若CRC碼有一位出錯,用G(x)作“模2除”運算,則得到一個不爲零的餘數,若對餘數補零,繼續作“模2除”運算,會得到一個有趣的結果:各次餘數會按表2.6中的順序循環.例如,第一位N1出錯,餘數將爲1,補零後再除,得到餘數爲010,以後依次爲100、011、…,反覆循環.這就是循環碼的由來.這個特點正好用來糾錯.當餘數不爲零時,一邊對餘數補零繼續作“模2除”運算,一邊將被檢測的CRC編碼循環左移.由表2.6可以看出,當出現餘數爲101時,出錯位也移到了N7位,可通過“異或門”將它們糾正後,再在下次移位時送回N7.然後繼續移位,直至移滿一個循環(對7,4碼,共移7次),就得到一個糾正後的碼字.
關於生成多項式
不是任何一個(r+1)位多項式都能作爲生成多項式,從檢錯、糾錯的要求來看,生成多項式應滿足下列要求:
① 任何一位發生錯誤,都應使餘數不爲零.
② 不同位發生錯誤,都應使餘數不同.
③ 對餘數補零,繼續作“模2除”,應使餘數循環.
反映這些要求的數學關係是比較複雜的,這裏不討論。