
循环冗余校验(cyclicredundancy check,CRC)对传输序列进行一次规定的除法操作,将除法操作的余数附加在传输信息的后面。在接收端,也对收到的数据做相同的除法。如果接收端除法得到的结果其余数不是零,就表明发生了错误。
循环冗余校验是将要发送的数据位序列当作一个多项式f(x)的系数,f(x)的系数只有1与0两种形式。在发送方用收发双方预定的约定的生成多项式G(x)去除,求得一个余数多项式。将余数多项式加到数据多项式之后发送到发送端。这里的除法是错位不减的模2减法,相当于异或运算。接收端采用同样的生成多项式G(x)去除接收到的数据多项式f’(x),如果传输无差错,则接收端除法运算f’(x)/G(x)的结果,其余数为零。否则就认为出现了差错。
基于除法的循环冗余校验,其计算量大于奇偶与求和校验,其差错检测的有效性也比较高,它能够检测出大约99.95%的错误。
CRC校验计算除法的公式举例

程序流程图

C程序
#include<stdio.h>
#include<stddef.h> //这个库里包含sizeof
int find(int a[],int n);
void display(int a[],int n);
int main()
{
int i,j,z;
long long num;
int snum[35]={0};
int res[51]={0}; //计算结果
int cal[51];
int ns;
int pol[17]={1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1};//CRC多项式
int np;
int first;
//输入学号进行并转成二进制
printf("请输入学号: ");
scanf("%lld",&num);
i=0;
j=2;
while(j) //除二的方法转成二进制
{
if(num%2==1)
{
snum[i]=1;
}
if(num%2==0)
{
snum[i]=0;
}
num=num/2;
if(num==0)
{
j--;
}
i++;
}
printf("\n学号的二进制:\n");
display(snum,35);
//进行计算准备(加尾部的零)
ns=sizeof(cal)/sizeof(cal[0]); //判断数组元素个数
np=sizeof(pol)/sizeof(pol[0]);
i=35+np-1;
j=0;
z=0;
while(i)
{
if(j<np-1)
{
cal[j]=0;
}
if(j>=np-1)
{
cal[j]=snum[z];
z++;
}
i--;
j++;
}
// 计算校验码
printf("\n采用CRC-16\n多项式为:x^16+x^15+x^2+1\n");
printf("\n输出计算过程:\n");
first=find(cal,ns);
display(cal,ns);
while(first>np-2) //按位异或
{
j=0;
for(i=first-np+1;i<=first;i++)
{
if(cal[i]==pol[j])
{
cal[i]=0;
}
else
{
cal[i]=1;
}
j++;
}
first=find(cal,ns);
display(cal,35+np-1);
}
//将原码与校验码合在一起
i=35+np-1;
j=0;
z=0;
while(i)
{
if(j<np-1)
{
res[j]=cal[j];
}
if(j>=np-1)
{
res[j]=snum[z];
z++;
}
i--;
j++;
}
printf("\n计算结果为:\n");
display(res,35+np-1);
//进行冗余检验
while(first>0) //按位异或
{
j=0;
for(i=first-np+1;i<=first;i++)
{
if(res[i]==pol[j])
{
res[i]=0;
}
else
{
res[i]=1;
}
j++;
}
first=find(res,ns);
}
printf("\n校验结果:\n");
display(res,35+np-1);
return 0;
}
int find(int a[],int n) //find函数给一个数组和其长度 找出第一个非零元素位置
{
int i;
i=n-1;
while(a[i]==0)
{
if(i==0)
{
break;
}
i--;
}
return i;
}
void display(int a[],int n) //显示数组
{
while(n)
{
printf("%d",a[n-1]);
n--;
}
printf("\n");
}
程序运行结果

程序的CRC校验码计算采用交互式的设计,输入一个数据进行计算反馈结果,并进行模拟校验,如果计算无误(在实际应用中传输无误)校验结果显示全为0