首页 > 编程知识 正文

crc32校验码在线计算(crc循环校验码)

时间:2023-05-05 23:33:50 阅读:73165 作者:2217

你知道,没有人会永远不出错。 同样,也没有永远不会出错的计算机和永远不会出错的数据。

人有认识错误就能改正的自觉,电脑上也有,但电脑没有人脑,只能用特定的方法自我修复。 这就是存在核对数字的必要性。

一般常用的校验码有奇偶校验码、CRC循环冗馀校验码、汉明校验码等。

这里只介绍使用最多的CRC循环冗馀校验码。

什么是校验码

校验码通过计算方法,发行方可以在原始数据的末尾添加一些数据,然后接收方通过计算计算出数据是否有误,将有错误的数据恢复为正确的数据。

例如,原始数据是1010,我们在其末尾添加一些数据,例如101,数据就变成了1010101,发送这个新数据; 如果发送过程中发生错误,数据变为1110101,则接收方可以根据1110101返回原始正确的数据1010。

CRC循环冗馀校验码的特点

CRC码是基于模式2运算建立编码规则的校验码。 (模式2运算可以简单地理解为异或运算。

编码方法:

1 .将原始数据用一个多项式m(x )=a*x^(n-1 ) b* x ^ (n-2 )… N*X^(1)1) P*X^(0)0)表示

例如,如果原始数据为1010,则表示为m(x )=1*X^(1)3)0* x ^ (2)=1*X^(1)0* x ^ (0)

2 .原始数据左移k位,得到m(x ) x^k,形成了n k位的信息。

上面的1010,向左移动了3位,得到了1010,000

3 .多项式m(x ) x^k除以特定生成多项式g ) x )的馀数是需要连接到原始数据末尾的CRC校验码。

示例:

已知原始数据为1100,生成多项式g(x )=1011时,求出CRC码的过程如下。

已知m(x )=1100=x^3x^2) n=4)

g(x )=1011=X^3 X^1 1

得k 1=n=4

要达到k=3,必须向左移动3位

因此,m(x ) x^3=1100,000

(m ) x ) x^3)/g ) x )的计算过程:

100,000 m (x ) x^3

是1011g(x )

-----------------

111 0多个,前0个省去; 然后,将馀数向左偏移1位,继续异或g(x )

1011g(x ) )。

-----------------

010左移1位,继续异或g(x )

10 11

-----------------

因为10k=3,所以到此为止将盈馀移动了2次。 还需要一次

最后计算的结果为010,原始数据为1100 010,最后三位是CRC代码。

在需要计算k位代码的情况下,很容易看出g(x )的位数是K 1。

最后的数据为7位,但有效数据还是4位,因此上述的1100 010代码也称为“7、4”代码,与“7、3”代码、“7、6”代码等对应。

CRC码的解码规则和纠错方法

还是刚才的例子,如果把最后出来的数据除以G(X ),剩下的数是0,这是正确的数据。

试着变更其中的1位,例如第2位。 得到1000 010。 如果将此数除以g(x ),则馀数为111,如果馀数不为0,则表示数据有误

与各位的错误对应的馀数如下所示。

序列号

N1 N2 N3 N4 N5 N6 N7

剩馀

错误位

正确的

1 1 0 0 0 1 0

000

错误

1 1 0 0 0 1 1

001

7

错误

1 1 0 0 0 0 0

010

6

错误

1 1 0 0 1 1 0

100

5

错误

1 1 0 1 0 1 0

011

4

错误

1 1 1 0 0 1 0

110

3

错误

1 0 0 0 0 1 0

111

2

错误

0 1 0 0 0 1 0

/p>

101

1

假如我们现在收到一个错误的信息是1000 010,通过计算可以得出余数是111,但是如何得知是第几位出错了?

我们试着对余数111补0后继续除下去,发现下一次的余数变成了101,继续下去,又变成了001,以后依次出现为010,100,011。。。反复循环,这就是“循环码”名字的由来。

这样,假如N2出现错误,则出现了不为0的余数后,一方面对余数补0继续模2除,另一方面将被检测的校验码字循环左移,当余数为101(即数据的首位为0)时,通过异或门可以将其纠正后在下一次移位时送回N2。这样当移满一个循环后,就得到一个纠正后的数据了。

最后给出几个标准

在上面的计算中可以发现,G(X)的作用非常重要,生成CRC码和译码都需要它。值得指出的是,并不是随便一个(K+1)位数据都可以作为生成多项式,它要满足的条件:

1.任何一位出错,都不能使余数为0,这是非常显然的;

2.不同位发生错误后,余数不能相同;

3.对余数继续模2除,应使余数循环。

为了方便起见,也为了标准化工作,现在一般用的生成多项式有以下几个:

CRC-16 = X16 + X15 + X2 + X0           美国二进制同步系统中采用

CRC-CCITT = X16 + X12 + X5 + X0        由欧洲CCITT 推荐

CRC-32 = X32 + X26 + X23 + X22 + X16 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + X0

下面贴出生成CRC码的代码

#include #include

using namespacestd;#define CRC_16 0x18005

//CRC-16 = X16 + X15 + X2 + X0

#define CRC_CCITT 0x11021

//CRC-CCITT = X16 + X12 + X5 + X0

#define CRC_32 0x104C11DB7

//CRC-32 = X32 + X26 + X23 + X22 + X16 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + X0

#define CHECK_CODE 0x8000

//check_code = x15,判断被除数位数>=16//check_code是为了每次做异或运算时保证位数是足够的

unsignedlong table[256];void build_16(unsigned longpoly)

{

unsignedlongx;

unsignedlongt;/*这里是将原始数据直接写入到t中

for (unsigned long i=0; i<256; i++)

{

x = i << 8;

t = 0;

for (unsigned long j = 0; j < 8; j++)

{

if ( (x ^ t) & CHECK_CODE)

t = (t << 1) ^ poly;

else

t <<= 1;

x <<= 1;

}

table[i] = ( unsigned long ) t;

}*/

//下面的是把余数和原始数据分开的写法//原始数据只有8位

for (int i=0; i<256; i++)

{

x= i<<8;//只移8位是为了位数对齐,因为下面的运算都是低位对齐的

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

{if (x&CHECK_CODE)

{

x<<= 1;

x= x^poly;

}else x <<= 1;

}

table[i]= (i<<16)+x;

}

}void build_32(unsigned longpoly)

{

unsignedlongx;for (unsigned long i=0; i<256; i++)

{

x= i<<24;for (unsigned long j=0; j<8; j++)

{if (x & 0x80000000) //判断位数是否足够,32位

{

x<<= 1;

x= x^poly;

}else x <<= 1;

}

table[i]= (i<<32)+x;

}

}intmain()

{

build_16(CRC_16);

build_16(CRC_CCITT);

build_32(CRC_32);for (int i=0; i<256; i++)

{if (i % 10 == 0)

cout<

printf("%lx", table[i]);

}return 0;

}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。