CRC演算法 個人學習筆記 直接法 查表法注意點

2021-08-13 06:48:48 字數 4296 閱讀 8598

crc

1、crc

演算法會根據選擇生成的檢驗碼的長度,需要設定乙個生成多項式,一般會使用國際上幾個大廠或者行業內的常用的標準多項式,而且這些標準還有其他選項細微的差別, 比如初始值的設定、是從資料的

msb/lsb

開始計算、結果是否需要與其他值異或等,以下是我找到的幾個通用演算法的配置資訊:

2、

演算法原理

(參考**4:

假設資料傳輸過程中需要傳送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-32、crc-64等。國際通行標準可以參看

g(x)和h(x)的除運算,可以通過g和h做xor(異或)運算。比如將11001與10101做xor運算:

明白了xor運算法則後,舉乙個例子使用crc-8演算法求101001110100001的效驗碼。crc-8標準的h(x) = x^8 + x^7 + x^6 + x^4 + x^2 +1,既h是9位的二進位制串111010101。 

經過迭代運算後,最終得到的r是10001100,這就是crc效驗碼。

通過示例,可以發現一些規律,依據這些規律調整演算法:

1. 每次迭代,根據gk

的首位決定b,b是與gk進行運算的二進位製碼。若gk的首位是1,則b=h;若gk的首位是0,則b=0,或者跳過此次迭代,上面的例子中就是碰到0後直接跳到後面的非零位。

2. 每次迭代,gk

的首位將會被移出,所以只需考慮第2位後計算即可。這樣就可以捨棄h的首位,將b取h的後m位。比如crc-8的h是111010101,b只需是11010101。

3. 每次迭代,受到影響的是gk

的前m位,所以構建乙個m位的暫存器s,此暫存器儲存gk的前m位。每次迭代計算前先將s的首位拋棄,將暫存器左移一位,同時將g的後一位加入暫存器。若使用此種方法,計算步驟如下:

※藍色表示暫存器s的首位,是需要移出的,b根據s的首位選擇0或者h。黃色是需要移入暫存器的位。s'是經過位移後的s。

3、舉個例子,計算單位元組

0x81

的crc8

的值(生成多項式:

0x07

,初始值

00,輸入輸出不反轉)

1) 將經0x81與初始值

0x00

進行異或

crc8 = 0x81 xor 0x00 = 0x81;

2) 從判斷資料的最高位,選擇對應的計算方法

1:資料左移一位,然後與多項式

0x07

進行異或,

crc8 = (crc8 << 1) ^ 0x07

0:資料左移一位,然後不動作,

crc8 =

(crc8 << 1)

3) 8位資料是否都移動完:

未移動完:返回第2步繼續計算

移動完:最後的結果則為最終的8位校驗值

4) 對應的c**

uint8_t get_crc8( uint8_t dat , uint8_t init_value)

return crc8;

}5) 以上是8位檢驗值的直接計算方法,16位

/32位也是同樣的。

4、crc16

、crc32

等多位元組的校驗值的計算有幾點需要清楚(只針對一次乙個位元組的演算法):

1) 初始值不為0的情況下,該如何計算:

輸入資料需要反**先將要計算的資料與初始值的最低位元組進行異或,再與反轉後的多項式進行計算。

輸入資料不需要反**先將要計算的資料左移到與初始值對齊的位置(如crc16演算法,則左移

8位,低位填充0;如

crc32

演算法,則左移

24位,低位填充

0)與初始值進行異或,再與正常的多項式進行計算。

2) 結果異或值不為0的情況:第一步算得到的

crc值再與結果異或值進行異或操作得到最終的校驗值:

輸出資料反**如果輸入資料是反轉的模式,則結果也是反轉的

輸出資料不反**如果輸入資料是不反轉的模式,則結果也是不反轉的

3)初始值的選擇是可自己定義,很多不同的廠家使用的初始值是不一樣,不一樣的初始值得到的結果也是不一樣的,要起到定製的效果,像上面提到的國際、行業使用的標準演算法,初始值是固定的。

5、使用查表法進行多位元組資料檢驗值計算時的演算法原理(可參考參考**

4中的推導部分):

1) crc8的查表法:要計算的單位元組資料與初始值進行異或得到單位元組資料,以此結果為表的序號從表中取得的值即為該位元組的校驗值;如果是多位元組,則以前一位元組的檢驗值作為初始值進行同樣的操作,演算法如下:

//結果不異或其他值

uint8_t get_crc8_with_table(uint8_t *datptr , uint8_t len , uint8_t init_value)

uint8_t crc8 = init_value;

while(len--)

crc8 = crc8_table[(*datptr++) ^ crc8];

return crc8;

2) crc16的查表法:要計算的單位元組資料與初始值的高位元組異或,然後以此單位元組資料作為表的序號從表中取得的值再與初始值的低位元組左移

8位後的值進行異或得到最終的檢驗值:

//輸入、輸出不反轉,結果不異或其他值

uint16_t get_crc16_with_table(uint8_t *datptr , uint8_t len , uint16_t init_value)

uint16_t crc16 = init_value;

while(len--)

return crc16;

3) crc32的查表法:要計算的單位元組資料與初始值的最高位元組異或,然後以此單位元組資料作為表的序號從表中取得的值再與初始值的低位元組左移

8位後的值進行異或得到最終的檢驗值:

//輸入、輸出不反轉的查表演算法,結果不異或任何值 

uint32_t get_crc32_with_table(uint8_t *datptr , uint8_t len , uint32_t init_value)

return crc32;

} //反轉輸入、輸出的查表演算法,結果異或0xffffffff 

uint32_t get_crc32_with_table_inv(uint8_t *datptr , uint8_t len , uint32_t init_value)

return crc32 ^ 0xffffffff;

}//生成輸入、輸出不反轉的表 

void crc32_table_init(void)

else

}crc32_table[i] = crc;}}

//生成輸入、輸出反轉的表 

void crc32_table_init_inv(void)

else

}crc32_table_inv[i] = crc;}} 

6、使用查表法需要注意的問題:

1) 關於表的生成,是以0~255這

256個數分別計算得到的

crc檢驗值,需要注意的是,此表的生成需要配合所使用的

crc演算法的配置,如輸入資料是否要反轉,輸入資料反轉和不反轉對應的表是不一樣的。還有很重要的一點,表的生成是以

初始值為0時

生成的檢驗值,否則會出錯,以下我是生成的表資料:

//輸入、輸出資料不反轉使用查表法時的表資料

uint32_t crc32_table[256] = ;

//輸入、輸出資料反轉使用查表法時的表資料

uint32_t crc32_table_inv[256] = ;

個人學習筆記 演算法 回溯法

回溯法通俗解釋 把所有的可能解做成解空間樹,遍歷這個數,如果路徑可行存下來,返回上乙個結點繼續遍歷 如果路徑不可行,直接返回上個結點重新遍歷,直到所有的結點遍歷完,得到需要的解。回溯法的特點 回溯法是通用的解題方法,也可以理解為試探法。可以求得問題的所有解或者任意解。採用樹的深度優先遍歷。適用於解的...

SAP BW個人學習筆記

sap bw個人學習筆記 難免有錯,持續更新,切勿對號入座。一 kpi 1 kpi是線性遞增的 2 kpi關鍵指標 一般情況下,2個模組,就有40個kpi,3個模組,有60多個kpi 二 增強 1 只有不符合要求時,才使用增強,還要使用標準字段。三 財務資料源 財務資料源是用的後像,也即是餘像,只能...

ajax個人學習筆記

1.function createxhr else if typeof activexobject undefined catch e else 2.ie瀏覽器第一次向伺服器端請求,獲取最新資料,其後預設獲取的是快取資料,而不是最新的資料,可以使用js中的隨機字串處理。3.ajax非同步 true ...