BCH码的基本原理参考了此处
【举例子详细分析】BCH码(BCH code)

文章目录

  • 模二多项式环
    • 代码实现
  • BCH码
    • 对信息编码

模二多项式环

模二多项式环中的一个多项式,和二进制数 是有一个由多项式的系数决定的,一一对应的关系的。
比如,有一个多项式
F(x)=x4+x+1F(x) = x^4 + x + 1F(x)=x4+x+1
将其系数为0的项补全后,可以得到
F(x)=1∗x4+0∗x3+0∗x2+1∗x+1F(x) = 1*x^4 + 0*x^3 + 0*x^2 + 1*x + 1F(x)=1∗x4+0∗x3+0∗x2+1∗x+1,
按顺序取出系数为10011

模二多项式环中的运算有关特性不再赘述

代码实现

class Polynomial2():'''模二多项式环,定义方式有三种一是>>> Polynomial2([1,1,0,1])x^3 + x^2 + 1二是>>> Polynomial2('1101')x^3 + x^2 + 1三是>>> Poly([3,1,4]) # 直接给出系数为1的项的阶x^4 + x^3 + x>>> Poly([])0'''def __init__(self,ll):if type(ll) ==  str:ll = list(map(int,ll))self.param = ll[::-1]self.ones = [i for i in range(len(self.param)) if self.param[i] == 1] # 系数为1的项的阶数列表self.Latex = self.latex()self.b = ''.join([str(i) for i in ll]) # 二进制形式打印系数self.order = 0 # 最高阶try:self.order = max(self.ones)except:passdef format(self,reverse = True):'''格式化打印字符串reverse = False时,可以低位在左但是注意定义多项式时只能高位在右'''r = ''if len(self.ones) == 0:return '0'if reverse:return ((' + '.join(f'x^{i}' for i in self.ones[::-1])+' ').replace('x^0','1').replace('x^1 ','x ')).strip()return ((' + '.join(f'x^{i}' for i in self.ones)+' ').replace('x^0','1').replace('x^1 ','x ')).strip()def __call__(self,x):# 懒得写print(f'call({x})')def __add__(self,other):a,b = self.param[::-1],other.param[::-1]if len(a) < len(b):a,b = b,afor i in range(len(a)):try:a[-1-i] = (b[-1-i] + a[-1-i]) % 2except:breakreturn Polynomial2(a)def __mul__(self,other):a,b = self.param[::-1],other.param[::-1]r = [0 for i in range(len(a) + len(b) - 1)]for i in range(len(b)):if b[-i-1] == 1:if i != 0:sa = a+[0]*ielse:sa = asa = [0] * (len(r)-len(sa)) + sa#r += np.array(sa)#r %= 2r = [(r[t] + sa[t])%2 for t in range(len(r))]return Polynomial2(r)def __sub__(self,oo):# 在模二多项式环下,加减相同return self + oodef div(self,other):r,b = self.param[::-1],other.param[::-1]if len(r) < len(b):return Polynomial2([0]),selfq=[0] * (len(r) - len(b) + 1)for i in range(len(q)):if len(r)>=len(b):index = len(r) - len(b) + 1  # 确定所得商是商式的第index位q[-index] = int(r[0] / b[0])# 更新被除多项式b_=b.copy()b_.extend([0] * (len(r) - len(b)))b_ = [t*q[i] for t in b_] r = [(r[t] - b_[t])%2 for t in range(len(r))]for j in range(len(r)):     #除去列表最左端无意义的0if r[0]==0:r.remove(0)else:breakelse:breakreturn Polynomial2(q),Polynomial2(r)def __floordiv__(self,other): # 只重载了整除,即//return self.div(other)[0]def __mod__(self,other):return self.div(other)[1]def __repr__(self) -> str:return self.format()def __str__(self) -> str:return self.format()def __pow__(self,a):# 没有大数阶乘的需求,就没写快速幂t = Polynomial2([1])for i in range(a):t *= selfreturn tdef latex(self,reverse=True):# Latex格式打印...其实就是给大于一位长度的数字加个括号{}def latex_pow(x):if len(str(x)) <= 1:return str(x)return '{'+str(x)+'}'r = ''if len(self.ones) == 0:return '0'if reverse:return (' + '.join(f'x^{latex_pow(i)}' for i in self.ones[::-1])+' ').replace('x^0','1').replace(' x^1 ',' x ').strip()return (' + '.join(f'x^{latex_pow(i)}' for i in self.ones)+' ').replace('x^0','1').replace(' x^1 ',' x ').strip()def __eq__(self,other):return self.ones == other.onesdef Poly(ones):if len(ones) == 0:return Polynomial2('0')ll = [0 for i in range(max(ones)+1)]for i in ones:ll[i] = 1return Polynomial2(ll[::-1])from tqdm import trange
from number import *PP = Polynomial2
P = Poly
# 简化名称,按长度区分 P 和 PP
'''
定义方式可改为
PP('11010')
或者
P([5,6,7])
'''

另外,在sagemath中有更强大的更完备的多项式整数环

sage: P.<x> = PolynomialRing(Zmod(2))sage: p = x^4 + x + 1sage: p(x^3)
x^12 + x^3 + 1sage: factor(p) # 分解多项式
x^4 + x + 1sage: factor(x^4+x^2+1) # 分解多项式
(x^2 + x + 1)^2

对这个不太熟悉,但功能没问题,主要用来检验结果

BCH码

原理大概是,根据编码纠错个数,Q(x)Q(x)Q(x) 有如下形式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FT2gSQOi-1659454509052)(Untitled%202.assets/9c2418c5823d42d89f917cb668638fa4.png)]
p(x)p(x)p(x) 是本原多项式primitive polynomial
选定 p(x)=x4+x+1p(x)=x^4 + x + 1p(x)=x4+x+1
p3(x)p_3(x)p3​(x) 满足 p3(x3)≡0modpp_3(x^3)\equiv 0\mod pp3​(x3)≡0modp
选定 p3(x)=x4+x3+x2+x+1p_3(x)=x^4 + x^3 + x^2 + x + 1p3​(x)=x4+x3+x2+x+1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Tg8CO4k-1659454509053)(Untitled%202.assets/9669eadfe0fc4983a64329cccd80c540.png)]
p5(x)p_5(x)p5​(x) 满足 p5(x5)≡0modpp_5(x^5)\equiv 0\mod pp5​(x5)≡0modp
选定 p5(x)=x2+x+1p_5(x)=x^2 + x + 1p5​(x)=x2+x+1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nm5xHjrq-1659454509054)(Untitled%202.assets/d3bdf9ab65e84ffebd58f2e5a4d03f36.png)]
假设需要纠错3位,则
Q(x)=p(x)∗p3(x)∗p5(x)Q(x)=p(x)*p_3(x)*p_5(x) Q(x)=p(x)∗p3​(x)∗p5​(x)

要发送的信息m(x)m(x)m(x),对其进行编码操作,得到的发送的信息S为
S(x)=Q(x)∗m(x)S(x) = Q(x) * m(x) S(x)=Q(x)∗m(x)
若发送过程不出错,则直接除以Q(x)Q(x)Q(x)即可得到原文m(x)m(x)m(x)

但若发送信息的过程中收到干扰,某几位比特出现错误,即接受到的信息R为
R(x)=Q(x)∗m(x)+xe1+xe2+xe3R(x) = Q(x) * m(x) + x^{e_1}+x^{e_2}+x^{e_3} R(x)=Q(x)∗m(x)+xe1​+xe2​+xe3​

由于之前p3(x)p_3(x)p3​(x)和p5(x)p_5(x)p5​(x)的性质,Q(x)Q(x)Q(x)也满足
Q(x3)≡0modpQ(x5)≡0modpQ(x^3)\equiv0\mod p\\ Q(x^5)\equiv0\mod p Q(x3)≡0modpQ(x5)≡0modp
所以
R(x)≡xe1+xe2+xe3modpR(x3)≡x3⋅e1+x3⋅e2+x3⋅e3modpR(x5)≡x5⋅e1+x5⋅e2+x5⋅e3modpR(x)\equiv x^{e_1}+x^{e_2}+x^{e_3}\mod p\\ R(x^3)\equiv x^{3·e_1}+x^{3·e_2}+x^{3·e_3}\mod p\\ R(x^5)\equiv x^{5·e_1}+x^{5·e_2}+x^{5·e_3}\mod p R(x)≡xe1​+xe2​+xe3​modpR(x3)≡x3⋅e1​+x3⋅e2​+x3⋅e3​modpR(x5)≡x5⋅e1​+x5⋅e2​+x5⋅e3​modp
这三个值都是已知的(可以求出的),根据这三个值,通过某些方法解出 e1,e2,e3e_1,e_2,e_3e1​,e2​,e3​ 的值,即可找出错误位置并纠正,得到 S(x)S(x)S(x),除以Q(x)Q(x)Q(x)即可得到原文 m(x)m(x)m(x)

对信息编码

假设要发送的信息 m = 11010

这里原paper里面是低位在左边
这里需要反序生成多项式

p = Polynomial2('10011')
p3 = Polynomial2('11111')
p5 = Polynomial2('111')
Q = p * p3 * p5print('p =',p.b)
print('p =',p)
print('p3 =',p3.b)
print('p5 =',p5.b)m = PP('01011')send = Q*m
print('send =',send.b)

p = 10011
p = x^4 + x + 1
p3 = 11111
p5 = 111
send = 010011011100001

ei1 = 2
ei2 = 5
e1 = Poly([ei1])
e2 = Poly([ei2])r = send + e1 + e2# r.ones是r中系数为1的项的阶数
# [3*i for i in r.ones]就是把所有阶数乘了3
r3 = Poly([3*i for i in r.ones]) # R(x^3)
r5 = Poly([5*i for i in r.ones]) # R(x^5)rx1 = r%p
rx3 = r3%p
rx5 = r5%pprint('rx1 =',rx1)
print('rx3 =',rx3)
print('rx5 =',rx5)

rx1 = x
rx3 = x^3 + x^2 + 1
rx5 = 0

原文中 R(x3)modp=x13R(x^3) \mod p=x^{13}R(x3)modp=x13
此处 x3+x2+1x^3 + x^2 + 1x3+x2+1 和 x13x^{13}x13 在modp\mod pmodp下是相同的

全部代码

from random import randintDEBUG = 0
# 如果开启DEBUG模式,则会打印中间值信息,并且按enter才会进入下一次恢复
# 不开启DEBUG,则while 1不断运行,捕捉到Ctrl+C中断时打印当前统计的成功率class Polynomial2():'''模二多项式环,定义方式有三种一是>>> Polynomial2([1,1,0,1])x^3 + x^2 + 1二是>>> Polynomial2('1101')x^3 + x^2 + 1三是>>> Poly([3,1,4]) # 直接给出系数为1的项的阶x^4 + x^3 + x>>> Poly([])0'''def __init__(self,ll):if type(ll) ==  str:ll = list(map(int,ll))self.param = ll[::-1]self.ones = [i for i in range(len(self.param)) if self.param[i] == 1] # 系数为1的项的阶数列表self.Latex = self.latex()self.b = ''.join([str(i) for i in ll]) # 二进制形式打印系数self.order = 0 # 最高阶try:self.order = max(self.ones)except:passdef format(self,reverse = True):'''格式化打印字符串reverse = False时,可以低位在左但是注意定义多项式时只能高位在右'''r = ''if len(self.ones) == 0:return '0'if reverse:return ((' + '.join(f'x^{i}' for i in self.ones[::-1])+' ').replace('x^0','1').replace('x^1 ','x ')).strip()return ((' + '.join(f'x^{i}' for i in self.ones)+' ').replace('x^0','1').replace('x^1 ','x ')).strip()def __call__(self,x):# 懒得写print(f'call({x})')def __add__(self,other):a,b = self.param[::-1],other.param[::-1]if len(a) < len(b):a,b = b,afor i in range(len(a)):try:a[-1-i] = (b[-1-i] + a[-1-i]) % 2except:breakreturn Polynomial2(a)def __mul__(self,other):a,b = self.param[::-1],other.param[::-1]r = [0 for i in range(len(a) + len(b) - 1)]for i in range(len(b)):if b[-i-1] == 1:if i != 0:sa = a+[0]*ielse:sa = asa = [0] * (len(r)-len(sa)) + sa#r += np.array(sa)#r %= 2r = [(r[t] + sa[t])%2 for t in range(len(r))]return Polynomial2(r)def __sub__(self,oo):# 在模二多项式环下,加减相同return self + oodef div(self,other):r,b = self.param[::-1],other.param[::-1]if len(r) < len(b):return Polynomial2([0]),selfq=[0] * (len(r) - len(b) + 1)for i in range(len(q)):if len(r)>=len(b):index = len(r) - len(b) + 1  # 确定所得商是商式的第index位q[-index] = int(r[0] / b[0])# 更新被除多项式b_=b.copy()b_.extend([0] * (len(r) - len(b)))b_ = [t*q[i] for t in b_] r = [(r[t] - b_[t])%2 for t in range(len(r))]for j in range(len(r)):     #除去列表最左端无意义的0if r[0]==0:r.remove(0)else:breakelse:breakreturn Polynomial2(q),Polynomial2(r)def __floordiv__(self,other): # 只重载了整除,即//return self.div(other)[0]def __mod__(self,other):return self.div(other)[1]def __repr__(self) -> str:return self.format()def __str__(self) -> str:return self.format()def __pow__(self,a):# 没有大数阶乘的需求,就没写快速幂t = Polynomial2([1])for i in range(a):t *= selfreturn tdef latex(self,reverse=True):# Latex格式打印...其实就是给大于一位长度的数字加个括号{}def latex_pow(x):if len(str(x)) <= 1:return str(x)return '{'+str(x)+'}'r = ''if len(self.ones) == 0:return '0'if reverse:return (' + '.join(f'x^{latex_pow(i)}' for i in self.ones[::-1])+' ').replace('x^0','1').replace(' x^1 ',' x ').strip()return (' + '.join(f'x^{latex_pow(i)}' for i in self.ones)+' ').replace('x^0','1').replace(' x^1 ',' x ').strip()def __eq__(self,other):return self.ones == other.onesdef Poly(ones):if len(ones) == 0:return Polynomial2('0')ll = [0 for i in range(max(ones)+1)]for i in ones:ll[i] = 1return Polynomial2(ll[::-1])from tqdm import trange
from number import *PP = Polynomial2
P = Poly
# 简化名称,按长度区分 P 和 PPp = Polynomial2('10011')
p3 = Polynomial2('11111')
Q = p*p3def getMorder(r,e1e2):return ((r+Poly(e1e2))//Q).orderdef main(mm):m = Polynomial2(bin(mm)[2:])send = Q*m                  # 发送的Send多项式ie1 = randint(0,send.order) # 随机选两个不相同的出错位置ie2 = randint(0,send.order)while ie1 == ie2:ie2 = randint(0,send.order)e1 = Poly([ie1])e2 = Poly([ie2])recv = send + e1 + e2       # 接收到的出错多项式rx = Poly([i for i in recv.ones])rx3 = Poly([3*i for i in recv.ones])if DEBUG:ff = max(len(recv.b),len(send.b))print('mm =',bin(mm)[2:])print('m =',m)print('p =',p)print('p3 =',p3)print()print('send:\t',send.b.zfill(ff))print('recv:\t',recv.b.zfill(ff))print('e:\t',(e1+e2).b.zfill(ff))print('e1,e2 =',ie1,ie2)print()print('R(x) =',rx)print('R(x) =',rx%p)print('R(x^3) =',rx3)print('R(x^3) =',rx3%p)ans = []for i in range(17):_e1 = Poly([i])for j in range(i,17):if i == j:continue_e2 = Poly([j])t1 = (_e1+_e2)%pt3 = (Poly([3*i])+Poly([3*j]))%pif DEBUG and i == ie1 and j == ie2:print('t1: ',t1)print('t3: ',t3)print(t1 == rx%p,t3 == rx3%p)if t1 == rx%p and t3 == rx3%p:#print('find',int(_e1.b,2),int(_e2.b,2),i,j)ans.append((i,j))if DEBUG:print('过滤前ans:',ans)if len(ans) > 1:# 若找到多组 e1e2,则判断(R-e1-e2)//p 的阶数是否小于8# 因为 m 的阶数不会超过8        res = [i for i in ans if getMorder(rx,i)<=7]else:res = ansif DEBUG:print('过滤后ans:',res,'出错位置:',(ie1,ie2))input()return resif __name__ == '__main__':cnt = [0,0,0,0,0]while 1:try:# 随机生成一个8bit明文cnt[len(main(randint(0,255)))] += 1# 返回值是结果列表 如果列表里只有一个元素则恢复成功# cnt 记录的是返回的列表的长度except:print('\n',cnt)if sum(cnt) != 0:sucP = (cnt[1]+cnt[2]/2+cnt[4]/4)/sum(cnt)print(f'p : {sucP},p^25:{sucP**25}')

模二多项式环 及 BCH码 的纯python实现和一些问题相关推荐

  1. PHP+MySql的网络验证源码开源纯代码可二次开发

    PHP+MySql的网络验证源码开源纯代码可二次开发 :99415656994962582靓仔担当有决心

  2. 二次解析源码全kyuan

    介绍: 紫胤二次解析源码纯kyuan 没有什么好说的,需要的下载吧 网盘下载地址: http://kekewangLuo.net/JCGIOeZfV0B 图片:

  3. logisim,quartus实现模为60的BCD码计数器

    一.分析:利用封装的74161完成带有异步复位端的模6和模10计数器,然后级联构成模为60的BCD码计数器: ​ 由74161功能表可知要构成模6计数器和模10计数器,可以采用同步置数法:当达到需要的 ...

  4. vc++6.0:MFC写的一个汉字取模软件(附源码)

    vc++6.0:MFC写的一个汉字取模软件(附源码) 一.毕业有九年了,突然想起以前在大学时候用MFC写的一个汉字取模软件.主要的功能是在PC上获取汉字16X16点阵数据然后通过串口把点阵数据发送给A ...

  5. C++ Opengl 绘制二次几何体源码

    C++ Opengl 绘制二次几何体源码 项目开发环境 项目功能 项目演示 项目源码传送门 项目开发环境 开发语言:C++和IDE:VS2017,操作系统Windows版本windows SDK8.1 ...

  6. 【BCH码2】BCH码的快速BM迭代译码原理详解及MATLAB实现(不使用MATLAB库函数-代码见CSDN同名资源)

    关注公号[逆向通信猿]更精彩!!! 理论基础 订阅<信道编码>专栏,首先查阅各子程序的详解 [有限域生成]本原多项式生成有限域的原理及MATLAB实现 [有限域除法]二元多项式除法电路原理 ...

  7. BCH码和m序列参数估计(梅西迭代算法求多项式的MATLAB实现)

    关注公众号[逆向通信猿]试读更多内容!!! 伯利坎普迭代算法解决了BCH码译码中求错位多项式 σ ( x ) \sigma (x) σ(x)的问题,即用迭代算法求解方程组,极大地加快了译码速度.求最短 ...

  8. 怎样查询2021高考模拟成绩,2021年高三一模二模三模哪个成绩更接近高考成绩,看看网友是怎么评论...

    2021年高三一模二模三模哪个成绩更接近高考成绩 虽然大多数人认为一模的成绩最接近高考,基本定型了,但高考变幻莫测,成绩很有可能发生变化,成绩升降都是很难说的. 高三一模之后成绩也没有定型,还有最后逆 ...

  9. 图解HTTP笔记(二)——HTTP状态码

    图解HTTP笔记(二)--HTTP状态码 本章的主要内容是了解HTTP状态码的工作机制 HTTP 常见的状态码,有哪些? 下面介绍一下常用的一些状态码. 一.1xx 提示信息 1xx 类状态码属于提示 ...

  10. NTL密码算法开源库——模二整数上的矩阵(mat_GF2)

    2021SC@SDUSC 模二整数上的矩阵(mat_GF2) 矩阵运算 高斯消元 矩阵运算 具体代码 #include <NTL/matrix.h> #include <NTL/ve ...

最新文章

  1. sortable 拖拽时互换目标的位置_双端通用型JS拖拽插件的封装与应用
  2. What's NEW in C++/CLI Language
  3. php 跳板机连接mysql,使用python如何通过跳板机连接MySQL数据库
  4. 精通 R plot—第1部分:颜色,图例和线
  5. Teams 可被滥用于安装恶意软件,微软或不打算修复
  6. 图像识别中——目标分割、目标识别、目标检测和目标跟踪的区别
  7. Matplotlib常用绘图示例
  8. ensp 交换机与路由器ospf_华为路由器 eNSP 配置 rip OSPF 路由重发布
  9. 软件实习项目4——校园一卡通管理系统(实验准备与设计)
  10. Maven项目中父子项目互相找不到的解决方法
  11. 微信接入之获取用户头像
  12. oracle获取timestamp日期,oracle日期时间型timestamp的深入理解
  13. 倍福--编码器链接到虚轴,虚轴不做控制,实轴做从轴,实现电子凸轮或电子齿轮的耦合
  14. 感性负载对电源的影响有多大?
  15. android地图画线,绘制折线-在地图上绘制-开发指南-Android 轻量版地图SDK | 高德地图API...
  16. midi java_java midi音乐文件播放器
  17. linux怎么生成图形,如何在Ubuntu 16.04中创建GIF动态图片
  18. 孙向晖-《领域驱动设计》读书心得交流会-UMLChina讲座-实录
  19. 史上最全!!!ARM架构下的NVIDIA Xavier安装ROS-Melodic以及使用速腾激光雷达+A-loam获取点云图
  20. 使用拼音搜索中文(转载)

热门文章

  1. 已知两点坐标求水平距离_知道两个点的坐标X,Y,如何计算出两点间的距离以及角度,公式是什么...
  2. vue省市区三级联动(行政区划代码)
  3. sql 左连接数据出现重复
  4. 数字图像处理(2)——数字图像获取
  5. linux卸载设备驱动命令,Linux设备驱动程序加载/卸载方法 insmod和modprobe命令
  6. python实现sm3加密算法
  7. KBQA-Bert学习记录-构建BERT-CRF模型
  8. FLUENT算例 —— Turbulent Pipe Flow (LES) 圆管湍流流动(大涡模拟)
  9. win7系统安装打印机驱动报错:Windows无法连接到打印机
  10. OC语言之Protocol基本使用