Python笔记-CRC循环冗余校验的编程实现

一、介绍

CRC算法详解

二、算法思想

在输入的时候是直接输入的生成多项式,而我们在计算CRC校验码的时候需要将生成多项式转换成对应的二进制串。
转换的方式如下图(x4表示的是x的4次方,生成多项式的1相当于X0

在这里插入图片描述

理解了转换的方法之后,就可以设计对应的算法了。
我的思路如下:

  • 先将传入的数据进行大写转换,以便之后的处理
  • 再以+号为标志将多项式分割成多个字符串,对于上图的样例来说就是分割成x4、x3和1
  • 将这些分割后的字符串存入一个列表lis
  • 由于生成多项式的最右侧必定为1,所以定义一个变量string直接初始化为列表的最后一个元素
  • 将列表的最后一个元素删除,并对列表进行逆序(相当于从右往左遍历生成多项式,且不遍历数字1
  • 遍历列表lis
  • 如果string的长度和X4、X3中的数字值相同时,就表示该位的二进制为1
  • 如果string遍历到X3却只有1位的长度时,就说明当前遍历到了X0的位置,但X2是不存在生成多项式中的,所以需要使用一个循环补全X2位置的0,由于之后需要在当前位置补1,则需要补0的个数为len(lis[i][1])-len(string)-1
def TurnBin(expression):
    '''将生成多项式转换为二进制字符串输出'''
    #输入数据处理
    expression = expression.upper()     #大写转换
    lis = list(expression.split("+"))   #以加号为标志进行分割
    string = lis[-1]                    #多项式末尾的数字1
    del lis[-1]
    lis = lis[::-1] #倒序
##    print(lis)
    #二进制转换
    for i in range(len(lis)): 
        if len(string)==int(lis[i][1]): #满足位数与变量的数字相同时
            string += "1"
        else:
            for j in range(int(lis[i][1])-len(string)): #用0补全相差的位数
                string += "0"
            string += "1"                
    return string[::-1]
  • 进行异或操作时,由于传入两个二进制串的前置0已经被消除过了。(主函数中需要使用到结果的尾数进行判断
  • 所以在进行异或时,可能会存在二进制串长度不同的情况
  • 则需要对输入的数据进行处理,添加较小二进制串的首部0使得两个二进制串位数相同。
  • 这样在异或运算时,只需要用一个循环同时遍历这两个字符串
  • 如果对应的二进制不同时,就为结果字符串result的末尾添1,否则添0
  • 最后输出的时候先遍历结果result,如果遇到第一个有效数据时,就将当前位置及其之后的字符串以切片的方式进行返回。(消除前置0
def XOR(string1,string2):
    '''将两个二进制串进行异或操作,不同为1'''
    result  = ""
    #输入数据处理
    if len(string1)<len(string2): #若前者的位数不足时
        for i in range(len(string2)-len(string1)): #对string1的首位补0
            string1 = "0" + string1
    if len(string1)>len(string2): #若后者的位数不足时
        for i in range(len(string1)-len(string2)): #对string2的首位补0
            string2 = "0" + string2
##    print(string1,string2)
    #异或计算
    for i in range(len(string1)):
        if string1[i]!=string2[i]:
            result += "1"
        else:
            result += "0"
##    print(result)
    #输出数据处理
    for i in range(len(result)):   #消除异或结果中的无效0
        if result[i]=="1": #找到第一个有效数据时
            return result[i::]
    return result
  • CRC函数中,先使用一个新的变量bin_expression保存生成多项式转换后的二进制串
  • 在计算时需要先在数据string末尾添加指定个数的00的个数等于多项式中的最高次方。
  • 由于在将多项式转换为二进制时将会多出来一位,所以添加0的个数就是len(bin_expression)-1
  • 然后遍历二进制数据
  • 先将数据string的每一个字符添加到异或结果字符串crc中,然后判断crc与除数bin_expression的位数
  • 如果位数相同时,就将两者传入XOR函数中进行异或操作,并返回结果给crc
  • 由于在校验码生成的过程中会删除前置0,所以需要补0的操作(正常来说是不需要删除多余的0,保险起见还是加了上去
def CRC(string,expression):
    '''产生CRC校验码'''
    crc = ""    #最终的crc校验码
    #输入数据处理
    bin_expression = TurnBin(expression)    #转换为二进制串
    for i in range(len(bin_expression)-1):  #在二进制串末尾补0
        string += "0"
##    print(string,bin_expression)
    #CRC计算
    for i in range(len(string)): #遍历被除数二进制串
        crc += string[i]
        if len(crc)==len(bin_expression): #当位数足够异或计算时
            crc = XOR(crc,bin_expression)
##    print(crc)
    #输出数据处理
    if len(crc)<len(bin_expression)-1: #当crc位数不足时
        for i in range(len(bin_expression)-len(crc)):   #在首部补0
            crc = "0" + crc
    if len(crc)>len(bin_expression)-1: #当crc位数过多时
        crc = crc[len(crc)-len(bin_expression)+1::] #切片,消除首部多余的0
    return crc
  • 在检验CRC的步骤使用的是之前的CRC函数
  • 传入的生成多项式同样需要经过二进制转换,传入二进制串数据的末尾是对应的校验码。
  • 计算CRC校验码时,切片的范围为[0,len(string)-len(bin_expression)+1 ]
  • 计算出来校验码后,就将计算出来的crc与原始数据的right_crc进行比对
  • 如果两个校验码相同,则表示数据传输正常。
  • 如果两个校验码不同,则表示数据传输出错。
def CheckCRC(string,expression): #检测传输数据是否正确,并打印结果
    #输入数据处理
    bin_expression = TurnBin(expression)                    #转换为二进制串
    right_crc = string[len(string)-len(bin_expression)+1::]   #原数据末尾的crc校验码
    #CRC计算
    crc = CRC(string[:len(string)-len(bin_expression)+1:],expression) 
    #检验
    if right_crc==crc:  #当尾部的CRC校验码,与首部数据生成的CRC校验码一致时
        print("数据传输过程正常..")
    else:
        print("数据传输过程出错..")
    print("检测出的校验码:",crc)
    print("数据尾部校验码:",right_crc)

剩下的代码属于主函数中界面的设计部分,就不详细介绍了

三、代码

在这里插入图片描述

再变更二进制数据的某些位,并在数据末尾添加原本数据产生的CRC校验码进行检测

在这里插入图片描述

将原始数据添加上对应的CRC校验码进行检测

在这里插入图片描述

# 作者:小狐狸
# 题目:CRC循环冗余校验
def TurnBin(expression):
    '''将生成多项式转换为二进制字符串输出'''
    #输入数据处理
    expression = expression.upper()     #大写转换
    lis = list(expression.split("+"))   #以加号为标志进行分割
    string = lis[-1]                    #多项式末尾的数字1
    del lis[-1]
    lis = lis[::-1] #倒序
##    print(lis)
    #二进制转换
    for i in range(len(lis)): 
        if len(string)==int(lis[i][1]): #满足位数与变量的数字相同时
            string += "1"
        else:
            for j in range(int(lis[i][1])-len(string)): #用0补全相差的位数
                string += "0"
            string += "1"                
    return string[::-1]

def XOR(string1,string2):
    '''将两个二进制串进行异或操作,不同为1'''
    result  = ""
    #输入数据处理
    if len(string1)<len(string2): #若前者的位数不足时
        for i in range(len(string2)-len(string1)): #对string1的首位补0
            string1 = "0" + string1
    if len(string1)>len(string2): #若后者的位数不足时
        for i in range(len(string1)-len(string2)): #对string2的首位补0
            string2 = "0" + string2
##    print(string1,string2)
    #异或计算
    for i in range(len(string1)):
        if string1[i]!=string2[i]:
            result += "1"
        else:
            result += "0"
##    print(result)
    #输出数据处理
    for i in range(len(result)):   #消除异或结果中的无效0
        if result[i]=="1": #找到第一个有效数据时
            return result[i::]
    return result

def CRC(string,expression):
    '''产生CRC校验码'''
    crc = ""    #最终的crc校验码
    #输入数据处理
    bin_expression = TurnBin(expression)    #转换为二进制串
    for i in range(len(bin_expression)-1):  #在二进制串末尾补0
        string += "0"
##    print(string,bin_expression)
    #CRC计算
    for i in range(len(string)): #遍历被除数二进制串
        crc += string[i]
        if len(crc)==len(bin_expression): #当位数足够异或计算时
            crc = XOR(crc,bin_expression)
##    print(crc)
    #输出数据处理
    if len(crc)<len(bin_expression)-1: #当crc位数不足时
        for i in range(len(bin_expression)-len(crc)):   #在首部补0
            crc = "0" + crc
    if len(crc)>len(bin_expression)-1: #当crc位数过多时
        crc = crc[len(crc)-len(bin_expression)+1::] #切片,消除首部多余的0
    return crc
    
def CheckCRC(string,expression): #检测传输数据是否正确,并打印结果
    #输入数据处理
    bin_expression = TurnBin(expression)                    #转换为二进制串
    right_crc = string[len(string)-len(bin_expression)+1::]   #原数据末尾的crc校验码
    #CRC计算
    crc = CRC(string[:len(string)-len(bin_expression)+1:],expression) 
    #检验
    if right_crc==crc:  #当尾部的CRC校验码,与首部数据生成的CRC校验码一致时
        print("数据传输过程正常..")
    else:
        print("数据传输过程出错..")
    print("检测出的校验码:",crc)
    print("数据尾部校验码:",right_crc)

if __name__=='__main__':
    while True:
        print("------------------------")
        print("|    0. 退出           |")
        print("|    1. 产生CRC校验码  |")
        print("|    2. 检测传输数据   |")
        print("------------------------")
        flag = int(input())
        if flag==0:
            break
        elif flag==1:
            expression = input("生成多项式: ")
            string = input("二进制串:")
            print(string,"的CRC校验码为: ",CRC(string,expression))
        elif flag==2:
            expression = input("生成多项式: ")
            string = input("二进制串:")
            CheckCRC(string,expression)

    print("程序已终止...")

  • 12
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦之海岛

创作不易,狐狸叹气

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值