CRC32演算法詳細推導(3)

2021-07-03 08:44:45 字數 2610 閱讀 4866

看起來我們已經得到 crc-32 演算法的最終形式了,可是、可是在實際的應用中,資料傳輸時是低位先行的;對於乙個位元組 byte 來講,傳輸將是按照 b1,b2,...,b8 的順序。而我們上面的演算法是按照高位在前的約定,不管是 reg還是 g(x) , g32,g31,...,g1 ; b8,b7,...,b1 ; r32,r31,...,r1 。

先來看看前面從 bit 轉換到 byte 一節中 for 迴圈的邏輯:

[cpp]view plain

copy

sum_poly = reg&0xff000000;  

for(

int j = 0; j < 8; j++)  

// 計算步驟2

reg = (reg<<8)|p[i];  

reg = reg ^ sum_poly;  

在這裡的計算中, p[i] 是按照 p8,p7,...,p1 的順序;如果 p[i] 在這裡變成了 p1,p2,...,p8 的順序;那麼 reg 也應該是 r1,r2,...,r32 的順序,同樣 g(x) 和 sum_poly 也要逆轉順序。轉換後的 g(x) = poly = 0xedb88320 。

於是取 reg 的最高位的 sum_poly 的初值就從 sum_poly = reg & 0xff000000 變成了 sum_poly = reg & 0xff,測試 reg 的最高位就從 sum_poly & 0x80000000 變成了 sum_poly&0x01 ;

移出最高位也就從 sum_poly<<=1 變成了 sum_poly>>=1 ;於是上面的**就變成了如下的形式:

[cpp]view plain

copy

sum_poly = reg&0xff;  

for(

int j = 0; j < 8; j++)  

// 計算步驟2

reg = (reg<<8)|p[i];  

reg = reg ^ sum_poly;  

為了清晰起見,給出完整的**:

[cpp]view plain

copy

// 以4 byte資料為例

#define poly 0xedb88320l // crc32生成多項式

unsigned int crc32_2(unsigned 

int data)  

// 計算步驟2

reg = (reg<<8)|p[i];  

reg = reg ^ sum_poly;  

}  return reg;  

}  

依舊像上面的思路,把計算 sum_poly 的**段提取出來,生成 256 個元素的 crc 校驗表,再修改追加 0 的邏輯,最終的**版本就完成了,為了對比;後面給出了位元組序逆轉前的完整**段。

[cpp]view plain

copy

// 位元組逆轉後的crc32演算法,位元組序為b1,b2,…,b8

#define poly 0xedb88320l // crc32生成多項式

static unsigned 

int crc_table[256];  

unsigned int get_sum_poly(unsigned 

char data)  

return sum_poly;  

}  void create_crc_table()  

}   

unsigned int crc32_4(unsigned 

char* data, int len)  

}  // 最終生成的校驗表將是:

//  

// 位元組逆轉前的crc32演算法,位元組序為b8,b7,…,b1

#define poly 0x04c11db7l // crc32生成多項式

static unsigned 

int crc_table[256];  

unsigned int get_sum_poly(unsigned 

char data)  

return sum_poly;  

}  void create_crc_table()  

}   

unsigned int crc32_4(unsigned 

char* data, int len)  

}  到這裡長征終於結束了, 事實上,還有最後的一小步,那就是 reg 初始值的問題,上面的演算法中 reg 初始值為 0 。在一些傳輸協議中,傳送端並不指出訊息長度,而是採用結束標誌,考慮下面的這幾種可能的差錯:

1 )在訊息之前,增加 1 個或多個 0 位元組;

2) 在訊息 ( 包括校驗碼 ) 之後,增加 1 個或多個 0 位元組;

顯然,這幾種差錯都檢測不出來,其原因就是如果 reg=0 ,處理 0 訊息位元組 ( 或位 ) , reg 的值保持不變。解決這種問題也很簡單,只要使 reg 的初始值非 0 即可,一般取 0xffffffff ,就像你在很多 crc32 實現中發現的那樣。

到這裡終於可以松一口氣了, crc32 並不是像想象的那樣容易的演算法啊!事實上還真不容易!這就叫做「簡單的前面是優雅,背後是複雜」!

CRC32演算法詳細推導(1)

from 作為blog再次發出來,詳細描述一下crc32演算法的推導過程。crc 演算法的數學基礎就不再多囉嗦了,到處都是,簡單提一下。它是以 gf 2 多項式算術為數學基礎的,gf 2 多項式中只有乙個變數 x 其係數也只有 0 和 1 比如 1 x 6 0 x 5 1 x 4 0 x 3 0 x...

CRC32演算法實現

crc32 檢錯能力極強,開銷小,易於用編碼器及檢測電路實現。從其檢錯能力來看,它所不能發現的錯誤的機率僅為0.0047 以下。從效能上和開銷上考慮,均遠遠優於奇偶校驗及算術和校驗等方式。因而,在資料儲存和資料通訊領域,crc無處不在 著名的通訊協議x.25的fcs 幀檢錯序列 採用的是crc cc...

深入了解crc32演算法

由於專案需要,解決乙個流 檔案的crc32校驗碼。網上查了很多的資料,發現了此校驗碼和生成多項式以及演算法本身都有關係。對於不同型別的檔案所使用的多項式以及演算法不同,對於不同的生成多項式所生成的crc32表不同,不同的演算法也會產生不同的結果。下面分模擬較兩種不同用途的crc32校驗碼的計算方法。...