循環冗餘檢驗 (CRC) 算法原理 html
Cyclic Redundancy Check循環冗餘檢驗,是基於數據計算一組效驗碼,用於覈對數據傳輸過程當中是否被更改或傳輸錯誤。 算法
假設數據傳輸過程當中須要發送15位的二進制信息g=101001110100001,這串二進制碼可表示爲代數多項式g(x) = x^14 + x^12 + x^9 + x^8 + x^7 + x^5 + 1,其中g中第k位的值,對應g(x)中x^k的係數。將g(x)乘以x^m,既將g後加m個0,而後除以m階多項式h(x),獲得的(m-1)階餘項r(x)對應的二進制碼r就是CRC編碼。 編碼
h(x)能夠自由選擇或者使用國際通行標準,通常按照h(x)的階數m,將CRC算法稱爲CRC-m,好比CRC-3二、CRC-64等。國際通行標準能夠參看http://en.wikipedia.org/wiki/Cyclic_redundancy_check spa
g(x)和h(x)的除運算,能夠經過g和h作xor(異或)運算。好比將11001與10101作xor運算: htm
明白了xor運算法則後,舉一個例子使用CRC-8算法求101001110100001的效驗碼。CRC-8標準的h(x) = x^8 + x^7 + x^6 + x^4 + x^2 + 1,既h是9位的二進制串111010101。
blog
通過迭代運算後,最終獲得的r是10001100,這就是CRC效驗碼。 ip
經過示例,能夠發現一些規律,依據這些規律調整算法:
1. 每次迭代,根據gk的首位決定b,b是與gk進行運算的二進制碼。若gk的首位是1,則b=h;若gk的首位是0,則b=0,或者跳過這次迭代,上面的例子中就是碰到0後直接跳到後面的非零位。 get
2. 每次迭代,gk的首位將會被移出,因此只需考慮第2位後計算便可。這樣就能夠捨棄h的首位,將b取h的後m位。好比CRC-8的h是111010101,b只需是11010101。
3. 每次迭代,受到影響的是gk的前m位,因此構建一個m位的寄存器S,此寄存器儲存gk的前m位。每次迭代計算前先將S的首位拋棄,將寄存器左移一位,同時將g的後一位加入寄存器。若使用此種方法,計算步驟以下:
import
※藍色表示寄存器S的首位,是須要移出的,b根據S的首位選擇0或者h。黃色是須要移入寄存器的位。S'是通過位移後的S。 原理
一樣是上面的那個例子,將數據按每4位組成1個block,這樣g就被分紅6個block。
下面的表展現了4次迭代計算步驟,灰色背景的位是保存在寄存器中的。
經4次迭代,B1被移出寄存器。被移出的部分,不咱們關心的,咱們關心的是這4次迭代對B2和B3產生了什麼影響。注意表中紅色的部分,先做以下定義:
B23 = 00111010
b1 = 00000000
b2 = 01010100
b3 = 10101010
b4 = 11010101
b' = b1 xor b2 xor b3 xor b4
4次迭代對B2和B3來講,實際上就是讓它們與b1,b2,b3,b4作了xor計算,既:
B23 xor b1 xor b2 xor b3 xor b4
能夠證實xor運算知足交換律和結合律,因而:
B23 xor b1 xor b2 xor b3 xor b4 = B23 xor (b1 xor b2 xor b3 xor b4) = B23 xor b'
b1是由B1的第1位決定的,b2是由B1迭代1次後的第2位決定(既是由B1的第1和第2位決定),同理,b3和b4都是由B1決定。經過B1就能夠計算出b'。另外,B1由4位組成,其一共2^4有種可能值。因而咱們就能夠想到一種更快捷的算法,事先將b'全部可能的值,16個值能夠當作一個表;這樣就能夠沒必要進行那4次迭代,而是用B1查表獲得b'值,將B1移出,B3移入,與b'計算,而後是下一次迭代。
可看到每次迭代,寄存器中的數據以4位爲單位移入和移出,關鍵是經過寄存器前4位查表得到
,這樣的算法能夠大大提升運算速度。
上面的方法是半字節查表法,另外還有單字節和雙字節查表法,原理都是同樣的——事先計算出2^8或2^16個b'的可能值,迭代中使用寄存器前8位或16位查表得到b'。
以前討論的算法能夠稱爲正向CRC算法,意思是將g左邊的位看做是高位,右邊的位看做低位。G的右邊加m個0,而後迭代計算是從高位開始,逐步將低位加入到寄存器中。在實際的數據傳送過程當中,是一邊接收數據,一邊計算CRC碼,正向算法將新接收的數據看做低位。
逆向算法顧名思義就是將左邊的數據看做低位,右邊的數據看做高位。這樣的話須要在g的左邊加m個0,h也要逆向,例如正向CRC-16算法h=0x4c11db8,逆向CRC-16算法h=0xedb88320。b的選擇0仍是h,由寄存器中右邊第1位決定,而不是左邊第1位。寄存器仍舊是向左位移,就是說迭代變成從低位到高位。