二维码三信息码的生成(手工制作)
采用的bch编码
一、BCH码基本原理
BCH码是一种有限域中的线性分组码,具有纠正多个随机错误的能力,通常用于通信和存储领域中的纠错编码。BCH码定义如下:给定任意一个有限域GF(q)及其扩展域GF(q^m),其中q是素数或素数的幂,m为正整数。对于任意一个码元取自扩展域GF(q^m)的循环码(n,k),其中n=2^m-1,其生成多项式g(x)具有2t个连续的根{a^1,a^2,a^,...,a^(2t-1),a^(2t)},则由生成多项式g(x)编码产生的循环码称为q进制的BCH码,记为(n,k,t)。当码长n=2^m-1,称为本原BCH码,否则称为非本原BCH码。
最常用的BCH码是二进制的BCH码。二进制BCH码的所有码元都是由0和1构成,便于硬件电路的实现。如无说明,本文以下讨论的BCH码都是二进制BCH码。二进制本原BCH码具有以下重要参数:
码长:n=2^m-1校验位长度:n-k<=m*t
BCH码的生成多项式是由GF(q^m)的2t个最小多项式最小公倍式的乘积,纠错能力为t的BCH码生成多项式为g(x)=LCM{m1(x),m2(x),...,m2t-1(x),m2t(x)},其中LCM表示最小公倍式,m(x)为最小多项式。
由多项式理论知道,如果有限域GF(2^m)中的元素a^i是m次即约多项式mi(x)的根,则(a^i)^2,(a^i)^4,(a^i)^8,...也是mi(x)的根,(a^i)^2,(a^i)^4,(a^i)^8,...称为共轭根系。如果两个根共轭,则它们具有相同的最小多项式。因此生成多项式g(x)=LCM{m1(x),m2(x),...,m2t-1(x),m2t(x)}=m1(x)*m3(x)*...*m2t-1(x)通过以上步骤就可以求出BCH码的生成多项式。得到生成多项式就可以对信息进行编码 [2] 。
其中mi(x)生成原理:
上述时定义以及m1(x),因此通过上面的讲述我们可以 得到
mi(x)=(x+a(i))(x+a(i*2)(x+a(i*2*2))....
注意:当i*2n如果此值大于2的15次方就需要将次 即对其15去摸 然后在对其刚才的约数 看是否有重复 如果有重复就 终止 并
移除此项
这是m1(x)的值 我们采用a4+a+1=0 来进行简化得 (注意:这里采用an+a+1它是an+1的一个因式,也可以采用an+1的其他因式,最好是采用最高次为n次的项,其他是否可以我没有测试)
注意:十进制的加法、减法在二进制中都是抑或,只有0 或者1
因此十进制相加后位偶数就位0 奇数就是1
m1(x)=x4+x+1?
a4=a+1
a5=a*a4=a*(a+1)=a2+a
a6=a*a5=a3+a2
a7=a*a6=a4+a3=a3+a+1
a8=a*a7=a*(a3+a+1)=a4+a2+a=a2+1
a9=a*a8=a(a2+1)=a3+a
a10=a*a9=a*(a3+a)=a4+a2=a2+a+1
a11=a*a10=a*(a2+a+1)=a3+a2+a
a12=a*a11=a*(a3+a2+a)=a4+a3+a2=a3+a2+a+1
a13=a*a12=a*(a3+a2+a+1)=a4+a3+a2+a=a3+a2+1
a14=a*a13=a*a3=a*(a3+a2+1)=a4+a3+a=a3+1
a15=a*a14=a*(a3+1)=a4+a=1=a0
Gf(16)中只有这十六个数
因此对应的数只有(0,a0,.....,a14)
然后我们将所得的结果带入刚才的公式m1(x)中
a+a2+a4+a8=(a+a4)+a2+a2+1=1+a2+a2+1=0
a3+a5+a9+a6+a10+a12=a3+(a2+a)+(a3+a)+(a3+a2)+
(a2+a+1)+(a3+a2+a+1)=0
a14+a13+a11+a7=(a3+1)+(a3+a2+1)+(a3+a2+a)+(a3+a+1)=1
a15=1;
因此m1(x)=x4+x+1
同理m3(x)等于m3(x)=(x+a3)(x+a6)(x+a12)(x+a24%15)
24%15=9前面几项中没有9因此 还要继续
m3(x)=(x+a3)(x+a6)(x+a12)(x+a9)(x+a(3*16)%15)
(3*16)%15)=3 前面几项中已存在因此 此项移除即
m3(x)=(x+a3)(x+a6)(x+a12)(x+a9)
=x4+(a3+a6+a9+a12)x3+(a9+a15+a12+a18+a15+a21)x2+x(a21+a18+a24+a27)+a30
=x4+(a3+a6+a9+a12)x3+(a9+a12+a18+a21)x2+x(a21+a18+a24+a27)++a30
=x4+(a3+a6+a9+a12)x3+(a9+a12+a3+a6)x2+x(a6+a3+a9+a12)+1
a3+a6+a9+a12=a3+(a3+a2)+(a3+a)+(a3+a2+a+1)=1
m3(x)=x4+x3+x2+x+1
次项关系式任何来的a4+a+1=0
f(x)=x4+x+1 他其实是x15+1的约多项式
因此我们在选择的时候本源多项式的时候 就选择f(x)=xlog2(n+1)+x+1
首先我们通过
若循环码的生成多项式具有如下形式(g(x)为最小公倍数)
g(x)=LCM[m1(x),m2(x),m3(x)..m2t−1(x)]
由于偶数项与前面的奇数项为共轭根系,有相同的最小多项式
因此g(x)=LCM[m1(x),m3(x)..m2t−1(x)]
例如:bch(15,5) n=4 t=3
g(x)=LCM[m1(x),m3(x),m5(x)]=m1(x)*m3(x)*m5(x)=(x4+x+1)*(x4+x3+x2+x+1)*(x2+x+1)=x10+x8+x5+x4+x2+x+1
Bch编码原理:
将未编码的k位数据记为多项式:
m(x)=m0+m1*x^1+m2*x^2+...+mk-1*x^k-1;其中mi属于{0,1}
将生成多项式记为:
g(x)=g0+g1*x1+g2*x^2+...+gr*x^r,其中r=m*t,校验位记为r(x),则
r(x)=x^r*m(x) mod g(x)
编码后的BCH码字多项式可记为:
C(x)=x^r*m(x)+x^r*m(x) mod g(x)
BCH编码实现的关键是通过除法电路得到校验位多项式。编码的过程可总结为:
1.将m(x)左移r位,得到x^r*m(x);
2.用生成多项式g(x)除以x^r*m(x),得到校验位多项式r(x);
3.得到码元多项式C(x)=x^r*m(x)+x^r*m(x) mod g(x)。
bch的生成多项g(x) 这里只支持bch(n,k);log2(n+1) 为整数,例如:7,15,31等。
多项式模2除法:
10111/11
10101
11000
01101
1100
0001 余数为1
1:
例如:数据码:00101
效验码:0011011100
bch编码:00101 0011011100(即数据码+校验码)
二、将bch编码与101010000010010进行抑或(bch编码为15位,其他的自己去查查就ok了)
xor:101010000010010
信息码:100000011001110
代码:
package com;
import java.util.*;
/**
* bch code码生成工具类
* Created by Administrator on 2020/5/22.
*/
public class makeBchCode {
public int[] bchCsArr;//二维码 bch数组 记录(n,k)
public int zgcNum;//最该此项 方便记录本源多项式 zgcNum=log2(n+1)
public String[] eleelementsArr;//存储元素数组
public LinkedHashMap<Integer, Map<Integer, Integer>> bcdCodeMap=new LinkedHashMap<Integer, Map<Integer, Integer>>();//bchcode集合
public String bchScCode;
public String bchCode;
public String infoCode="";
public String data;
public Map<Integer,String> xorMap=new HashMap<Integer, String>();
//a4+a+1=0;
public makeBchCode(){}
public makeBchCode(int[] bchCsArr,String data){
this.bchCsArr=bchCsArr;
this.zgcNum= (int) (Math.log(bchCsArr[0]+1) / Math.log(2));
this.data=data;
if(stringEjzZhSjz(data)==0){
//bchCode=xorMap.get(bchCsArr[0]);
for(int i=0;i<bchCsArr[0]-bchCsArr[1];i++){
bchCode+="0";
}
infoCode=data+bchCode;
return;
}
makeXorMap();
makeEle();
mkEwmBchCode();
mkBchCode();
}
/*
*xor集合生成
* */
public void makeXorMap(){
xorMap.put(15,"101010000010010");
}
/*
* 生成元素表方法
*采用迭代的方式 如果指数小于zgcNum 其值就是本身 a0=1 a2zgcNum=1
* 如果指数等于zgcNum=a+1 即a zgcNum=a+1;
* 如果指数大于zgcNum 即将指数为zgcNum的转换为zgcNum=a+1 在进行计算 注:需要移除通向项;
* */
public void makeEle(){
eleelementsArr=new String[(int)Math.pow(zgcNum,2)];
for(int i=0;i<eleelementsArr.length;i++){
if(i==0||i==eleelementsArr.length-1){
eleelementsArr[i]="0";
}else if(i<zgcNum){
eleelementsArr[i]=i+"";
}else if(i==zgcNum){
eleelementsArr[i]="10";
}else{
String slast=eleelementsArr[i-1];
String sbf="";
String[] ar=slast.split("");
for(int j=0;j<ar.length;j++){
if(Integer.valueOf(ar[j])+1==zgcNum){
sbf+=("10");
}else{
sbf+=(Integer.valueOf(ar[j])+1)+"";
}
}
ArrayList<String> strInt=new ArrayList<String>();
for(int l=0;l<sbf.length();l++){
String s=sbf.substring(l,l+1);
if(sbf.lastIndexOf(s)>sbf.indexOf(s)&&(strInt.isEmpty()||!strInt.contains(s))){
strInt.add(s);
}
}
if(!strInt.isEmpty()){
for(int l=0;l<strInt.size();l++){
sbf=sbf.replace(strInt.get(l),"");
}
}
eleelementsArr[i]=sbf;
}
}
}
/*
* bchCode生成
* bchcode=数据码/生成多项式 的余数
* infoCode生成 =bchCode 与 xor 掩码前的编码 进行抑或
* */
public void mkBchCode(){
int length=bchScCode.length()-bchScCode.indexOf("1")-1;
int a= stringEjzZhSjz(data)*(int)(Math.pow(2,length));
int b=stringEjzZhSjz(bchScCode);
String str=Integer.toBinaryString(a);
int c=0;
List<Integer> list=new ArrayList<Integer>();
while(true){
if(str==null||str.length()<bchScCode.length()){
break;
}
list.clear();
for(int i=0;i<bchScCode.length();i++){
if(bchScCode.substring(i,i+1).equals("1")){
list.add(str.length()-i-1);
}
}
for(int i=0;i<str.length();i++){
if(str.substring(i,i+1).equals("1")){
list.add(str.length()-i-1);
}
}
c=0;
for(int i=0;i<list.size();i++){
if(list.indexOf(list.get(i))==list.lastIndexOf(list.get(i))){
c+=Math.pow(2,list.get(i));
}
}
str=Integer.toBinaryString(c);
}
int len=bchCsArr[0]-bchCsArr[1]-str.length();
if(len>0){
for(int i=0;i<len;i++){
str="0"+str;
}
}
bchCode=data+str;
for(int i=0;i<bchCsArr[0];i++){
int num1=Integer.valueOf(bchCode.substring(i,i+1));
int num2=Integer.valueOf(xorMap.get(bchCsArr[0]).substring(i,i+1));
if(num1+num2==1){
infoCode+="1";
}else{
infoCode+="0";
}
}
}
/*
* bchScCode生成 由于我们不知道 t的值 因此也不知道 d 的值
* 但是可以得到 生成多项式的最高此项 就为bchCsArr[0]-bchCsArr[1]
* 因此当 指数大于他的时候 就退出循环
* */
public void mkEwmBchCode(){
for(int i=1;i<=7;i+=2){
if(!bcdCodeMap.isEmpty()){
int a=0;
for(int key:bcdCodeMap.keySet()){
int b=0;
for(int key2:bcdCodeMap.get(key).keySet()){
b=Math.max(b,key2);
}
a+=b;
}
if(a>=bchCsArr[0]-bchCsArr[1]){
break;
}
}
makeZxDxs(i);
}
List<Map<Integer,Integer>> listBch=new ArrayList<Map<Integer, Integer>>();
//bcdCodeMap
List<Integer> listBchJgList=new ArrayList<Integer>();
Map<Integer,Integer> map=new HashMap<Integer, Integer>();
Map<Integer,Integer> map2=new HashMap<Integer, Integer>();
for(int key:bcdCodeMap.keySet()){
listBch.add(bcdCodeMap.get(key));
}
for(int i=0;i<listBch.size();i++){
if(i==0){
map=listBch.get(0);
}
if(i<listBch.size()-1){
for(int key:listBch.get(i+1).keySet()){
for(int key1:map.keySet()){
listBchJgList.add(key+key1);
}
}
System.out.println("dcMap:"+listBchJgList);
map.clear();
map2.clear();
for(int j=0;j<listBchJgList.size();j++){
if(!map2.isEmpty()&&map2.containsKey(listBchJgList.get(j))){
continue;
}
int count=1;
for(int l=j+1;l<listBchJgList.size();l++){
if(listBchJgList.get(l)==listBchJgList.get(j)){
count++;
}
}
if(count%2==1){
map2.put(listBchJgList.get(j),1);
}else{
map2.put(listBchJgList.get(j),0);
}
}
listBchJgList.clear();
for(int key:map2.keySet()){
if(map2.get(key)!=0){
map.put(key,1);
}
}
}
}
if(!map.isEmpty()){
bchScCode="";
for(int key:map.keySet()){
if(bchScCode.length()<=key){
String str="1";
for(int i=0;i<key-bchScCode.length();i++){
str+="0";
}
bchScCode=str+bchScCode;
}else{
bchScCode=bchScCode.substring(0,key)+"1"+bchScCode.substring(key+1,bchScCode.length());
}
}
}
System.out.println("jhMap:"+map);
}
/*
* 生成最小多项式
* mi(x)=(x+a(i))(x+a(i*2)(x+a(i*2*2))....
*注意:当i*2n如果此值大于2的15次方就需要将次 即对其15去摸 然后在对其刚才的约数 看是否有重复 如果有重复就 终止 并
*移除此项
* */
public void makeZxDxs(int num){
Stack stack=new Stack<Class<bchDxs>>();
bchDxs bch;
LinkedHashMap<Integer,List<Integer>> backDxsZkMap;
List<Integer> listRootXs=new ArrayList<Integer>();
while(true){
if(stack.isEmpty()){
backDxsZkMap=new LinkedHashMap<Integer,List<Integer>>();
listRootXs.add(num);
}else{
int rootXs= (int) (num*Math.pow(2,listRootXs.size()));
rootXs=(rootXs>bchCsArr[0])?(rootXs%bchCsArr[0]):rootXs;
if(listRootXs.contains(rootXs)){
break;
}
listRootXs.add(rootXs);
bch=(bchDxs)stack.peek();
backDxsZkMap=bch.dxsZkMap;
}
bchDxs bds=new bchDxs(listRootXs.size(),num,backDxsZkMap);
stack.add(bds);
}
bch=(bchDxs)stack.peek();
dxsJh(bch.dxsZkMap,num);
}
/*
* 多项式简化(利用元素表)
* 多项式简化的时候 有一个小技巧(如果不会只能自己将多项式系数的元素表的转换来进行抑或运算)
* 例如:a+a2+a4+a8=a+a2+a+1+a2+1 进行抑或运算(a+a)+(1+1)+(a2+a2)=0
* 由于我们最小多项式的系数不是0 就是1 因此只要我们将多项式的系数转换成运算表进行计算
* 只要是偶数 就为0 只要是奇数 就为1 偶数全部抑或掉了 奇数表示有某一项没有抑或掉 就是1
* */
public void dxsJh(LinkedHashMap<Integer,List<Integer>> dxsZkMap,int num){
Map<Integer,Integer> map=new HashMap<Integer, Integer>();
StringBuffer sbf;String str="";
for(int key:dxsZkMap.keySet()){
sbf=new StringBuffer("");
for(int i=0;i<dxsZkMap.get(key).size();i++){
int a=dxsZkMap.get(key).get(i)%15;
sbf.append(eleelementsArr[a]);
}
if(sbf.length()%2==1){
map.put(key,1);
}
}
bcdCodeMap.put(num,map);
System.out.println(num+"map:"+map);
}
/*
* 二进制字符串转换为 十进制
* */
public int stringEjzZhSjz(String str){
int a=0;
if(str!=null&&str.length()>0){
for(int i=0;i<str.length();i++){
if(str.substring(i,i+1).equals("1")){
a+=Math.pow(2,str.length()-i-1);
}
}
}
return a;
}
/*
* 进行多项式展开需要将f(n)x=f(n-1)x*(x+a(n*2*2)%bchCsArr[0])
* 因此采用深度算法
*
* 采用错位相加法 例如:f(n-1)x=b0x(n-1)+b1x(n-2)+...+b(n-1)x0
* f(n)x=(b0x(n-1)+b1x(n-2)+...+b(n-1)x0)(x+c)
* =b0x(n-1+1)+b1x(n-2+1)+...+b(n-1)x0+1
* + cb0x(n-1)+cb1x(n-2)+...+cb(n-2)x1+cb(n-1)x0
* =b0x(n-1+1)+(b1+cb0)x(n-1)+...+(b(n-1)+cb(n-1))x1+cb(n-1)x0
* 下面的集合就是记录每个多项式的系数
* */
class bchDxs{
public int deep;//展开的深度也就是n
public int lcmDeep;//lcm函数的深度
public LinkedHashMap<Integer,List<Integer>> backDxsZkMap;//f(n-1)x的多项式展开集合
public LinkedHashMap<Integer,List<Integer>> dxsZkMap=new LinkedHashMap<Integer, List<Integer>>();//f(n)x的多项式展开集合
public bchDxs(){}
public bchDxs(int deep,int lcmDeep,LinkedHashMap<Integer,List<Integer>> backDxsZkMap){
this.backDxsZkMap=backDxsZkMap;
this.deep=deep;
this.lcmDeep=lcmDeep;
makeBchDxs();
}
public void makeBchDxs(){
if(deep==1){
List<Integer> list1=new ArrayList<Integer>();
List<Integer> list0=new ArrayList<Integer>();
list1.add(0);
list0.add(lcmDeep);
dxsZkMap.put(1, list1);
dxsZkMap.put(0,list0);
return;
}
int a= (int) (lcmDeep*Math.pow(2,deep-1));
for(int key:backDxsZkMap.keySet()){
List<Integer> listKey=new ArrayList<Integer>();
if(key==deep-1){
listKey.add(0);
dxsZkMap.put(deep,listKey);
}else{
for(int i=0;i<backDxsZkMap.get(key).size();i++){
listKey.add(backDxsZkMap.get(key).get(i));
}
if(backDxsZkMap.containsKey(key+1)){
for(int i=0;i<backDxsZkMap.get(key+1).size();i++){
listKey.add(a+backDxsZkMap.get(key+1).get(i));
}
}
dxsZkMap.put(key+1,tcCf(listKey));
if(key==0){
List<Integer> listLast=new ArrayList<Integer>();
listLast.add(a+backDxsZkMap.get(key).get(0));
dxsZkMap.put(key,listLast);
}
}
}
System.out.println(dxsZkMap);
}
/*
* 数组里面剔除重复的 因为重复的抑或后为0
* */
public List<Integer> tcCf(List<Integer> listKey){
List<Integer> list=new ArrayList<Integer>();
for(int i=0;i<listKey.size();i++){
if(listKey.lastIndexOf(listKey.get(i))>listKey.indexOf(listKey.get(i))){
continue;
}
list.add(listKey.get(i));
}
return list;
}
}
public static void main(String[] args) {
int[] arr=new int[]{15,5};
String aa="10010";
String[] aaa=new String[]{"10000","10001","10010","10011","10100","10101","10110","10111"};
for(int i=0;i<8;i++){
makeBchCode m=new makeBchCode(arr,aaa[i]);
System.out.println("aa[i]"+aaa[i]);
System.out.println("infoCode"+m.infoCode);
}
}
}