二维码二之纠错码手工制作(全部手工不用查表)

二维码纠错码生成原理:

一、数据码字多项式v1(数据码与纠错码字数表)

1

26

L

7

1

(26,19,2)†

 

 

M

10

1

(26,16,4)†

 

 

Q

13

1

(26,13,6)†

 

 

H

17

1

(26,9,8)†


例如根据数据码编码,版本1,数字编码模式,纠错等级Q,对"01234567"进行数据码编码,数据码就应该为13 纠错码也为13

因此位流为00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100

数据码字多项式系数
16 32 12 86 97 128 236 17 236 17 236 17 236

那么生成多项式的深度就应该为13

二.生成多项式:(下面有方法直接生成)

 (x+a0)(x+a1)(x+a2)(x+a3)..(x+a13)就是他的展开式

1.    多项式系数采用GF(256) GF(256)是啥?QR Code标准表示使用逐位模2算术和逐字节模100011101算法,也就是使用伽罗瓦域2^8,或者伽罗瓦域256,有时写为GF(256)。    GF(256)的范围是0~255。简而言之,在这个神奇的领域里面,超过255是不允许的,一旦超过就要通过异或的方式来降一降。   比如说2^8=256,因此需要和100011101进行异或操作来得到最终的值,所以2^8=256^285=58。2^9=58*2=116。2^10=116*2=232。……

注意:幂超过255需要对256取模求余数

 GF(256)表下面有方法直接生成,不用去查任何表。

GF(256)表生成原理:由于幂超过255需要对256去模,表示超过255后GF(256)的数会出现重复,

                                 那么在0-255之间的GF(256)的值不会出现重复,所以我们只需要遍历指数0--255的伽罗华域值,

                                 将它存储在一张表上,以后就可以直接查找运用了。

2.采用多项式直接展开(对于数学较好的人可以挑战下 难度较大,有点像组合排序求概率)
   分析(x+a0)(x+a1)(x+a2)(x+a3)..(x+an-1)
   首先我们假设有0 1 2 3 。。 n-1 n个数
   我们分析xr一项系数为(我们选择n-r个数即未选中r个数)未选中的r个数的和
   因此xr的多项式系数就是所有 xr单项系数的和(即所有选择n-r个数,未选中的r个数的和的总和)

3.生成多项式方法二:采用深度

  思路:先获取 1次 一项式展开式 x+a0  1
  在获取2次  二项式展开式(x+a0)(x+a1)=x2+a0^a1x+a0*a1  2
                     .....

   获取n次   n项式展开式就为n-1的展开式乘以x+an-1    n
   方法是采用错位相加的办法 如 deep=3 可以得到 deep=2 是的多项式为 x2+3x+2
   那么deep=3的多项式为(x2+3x+2)(x+4)
                                          x3+3x2+2x
                                        +     4x2+12x+8
                                          =x3+7x2+14x+8

三、纠错码生成:数据码多项式向左移动13位(纠错码数量)即由以前的

:16x12+32x11+12x10+86x9+97x8+128x7+236x6+17x5+236x4+17x3+236x2+17x+236

变更为16x25+32x24+12x13+86x22+97x21+128x20+236x19+17x18+236x17+17x16+236x15+17x14+236x13

生成多项式:α0x13 + α74x12 + α152x11 + α176x10 + α100x9 + α86x8 + α100x7 + α106x6 + α104x5 + α130x4 + α218x3 + α206x2 + α140x + α78

纠错码多项式=数据码多项式%生成多项式  (余数位纠错码多项式)

代码:

package com;

import java.util.*;

/**
 * 生成纠错码工具类
 * Created by 常发均 on 2020/5/19.
 */
public class makeJcm {
    public Map<Integer,Integer> map;
    public int[] jcmArr;
    public makeJcm(){
        map=getJlub();
    }
    /*
    * 生成多项式方法一:
    * @params 中num 表示纠错码的数量
    * 注意 幂超过255需要对256取模求余数
    *     多项式系数采用GF(256)
    *     GF(256)是啥?QR Code标准表示使用逐位模2算术和逐字节模100011101算法,也就是使用伽罗瓦域2^8,或者伽罗瓦域256,有时写为GF(256)。
    *     GF(256)的范围是0~255。简而言之,在这个神奇的领域里面,超过255是不允许的,一旦超过就要通过异或的方式来降一降。
    *     比如说2^8=256,因此需要和100011101进行异或操作来得到最终的值,所以2^8=256^285=58。2^9=58*2=116。2^10=116*2=232。……
    *     思路:采用多项式直接展开(对于数学较好的人可以挑战下 难度较大)
    *     分析(x+a0)(x+a1)(x+a2)(x+a3)..(x+an-1)
    *     首先我们假设有0 1 2 3 。。 n-1 n个数
    *     我们分析xr一项系数为(我们选择n-r个数即未选中r个数)未选中的r个数的和
    *     因此xr的多项式系数就是所有 xr单项系数的和(即所有选择n-r个数,未选中的r个数的和的总和)
    * */
    public int[] makeDxs(int num){
        num=num+1;
        if(num==0){
            try {
                throw new Exception("不可没有纠错码!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        int[] arrDxs=new int[num];//数组从左向右表示多项式系数逐渐变低
        Map<Integer,ArrayList<ArrayList<Integer>>> map=new HashMap();//集合为了记录所有多项式对应的选择的数
        /*
        * 这里采用算发为 假如选择r个数 总数为n
        * 选数方式:第一次  0,1,2,3.。。。 n-r-1 所有数选择 并存入集合 (n-r-1 表示最后一次选择为 距第n项r个数,因此如果在往后 就选不了那么多数了 没有那么多)
        *           第二次 需要在第一次基础上   例如:第一次 选0这个数 第二次 就1,2,3.。。。 n-r-2 就在第一次选择数的基础上往右移1位 并存入集合
        *                                             第一次 选1这个数 第二次 就1,2,3.。。。 n-r-2 就在第一次选择数的基础上往右移2位  并存入集合
        *                                             ....
        *                                             第一次选择完成后 在将我们选择数的集合移除掉,添加进 此次的集合
        * 注:选择的数是没有顺序的,因此我们采用从小到大进行选数 避免重复
        *
        * */
        for(int i=0;i<num;i++){
            ArrayList<ArrayList<Integer>> alist=new ArrayList<ArrayList<Integer>>();
                for(int l=1;l<=i;l++){
                    ArrayList<ArrayList<Integer>> alist2=new ArrayList<ArrayList<Integer>>();
                    for(int j=l-1;j<num+l-1-i;j++){
                        if(l==1){
                          ArrayList al=new ArrayList<Integer>();
                          al.add(j);
                          alist.add(al);
                        }
                        else{
                            for(int m=0;m<alist.size();m++){
                                if(alist.get(m).get(alist.get(m).size()-1)<j){
                                    ArrayList<Integer> ls=new ArrayList<Integer>();
                                    ls= (ArrayList<Integer>) alist.get(m).clone();
                                    ls.add(j);
                                    alist2.add(ls);
                                }
                            }
                        }
                    }
                    if(!alist2.isEmpty()){
                        alist.clear();
                        alist= (ArrayList<ArrayList<Integer>>) alist2.clone();
                    }
                }
            map.put(i,alist);
        }
        for(int i=0;i<map.size();i++){
            if(!map.get(i).isEmpty()){
                int c=0;
               for(int j=0;j<map.get(i).size();j++){
                   int b=0;
                   for(int l=0;l<map.get(i).get(j).size();l++){
                       /*
                       * 指数大于256需要去256摸
                       * */
                       b=(b+map.get(i).get(j).get(l))>256?(b+map.get(i).get(j).get(l))%256:(b+map.get(i).get(j).get(l));
                   }
                   /*
                   * 然后再采用伽罗华域相加的法则相加
                   * */
                   c=((c^getAlpha(b))>256)?(c^getAlpha(b))^285:(c^getAlpha(b));
               }
                /*
                * 将最后转换的十进制存入数组
                * */
                arrDxs[i]=c;
            }else{
                arrDxs[i]=1;
            }
        }
        System.out.println("arr");
        for(int i=0;i<arrDxs.length;i++){
            System.out.print(i+"=="+arrDxs[i]+"    ");
        }
        System.out.println();
        System.out.println("arrDxs");
        return arrDxs;
    }
    /*
    * 生成多项式深度算法
    * */
    public int[] makeDxsDeep(int num){
        //num=num+1;
       /*
       * 由于我们每次都需要取出上一次存入的类 因此使用堆栈
       * 先进后出原则
       * */
        Stack stack=new Stack<Class<jcmDxs>>();
        jcmDxs backDxs;
        for(int i=0;i<num;i++){
            int[] arr;
            if(i==0){
                arr=new int[]{1};
            }else{
       /*
        * 取出栈顶元素
        * */
             backDxs=(jcmDxs)stack.peek();
             arr=backDxs.dxsArr;
            }
            jcmDxs dxs=new jcmDxs(arr,i,map);
            stack.add(dxs);
        }
        backDxs=(jcmDxs)stack.peek();
        return backDxs.dxsArr;
    }
    public void makeQrJcm(int[] xsDxs,int[] scDxs){
        jcmArr=new int[scDxs.length-1];
        Stack stack=new Stack<int[]>();
        stack.add(xsDxs);
        for(int i=0;i<xsDxs.length;i++){
            int[] arr= (int[]) stack.peek();
            int length=(arr.length-1)<scDxs.length?scDxs.length:(arr.length-1);
            int[] arrLsXsDxs=new int[length];
            /*
            * 由于数据数组长度有可能小于生成码数组长度因此 取其较大值
            * */

            for(int j=1;j<Math.max(arr.length,scDxs.length);j++){
               /*
                * 表示j在数据码或者生成码范围内 就取数组对应的值
                * 否则就为0
                * */
             int a=0;int b=0;
                if(j<scDxs.length){
                    a=getAlpha(map.get(scDxs[j])+map.get(arr[0]));
                }
                if(j<arr.length){
                    b=arr[j];
                }
                arrLsXsDxs[j-1]=(b^a)>256?(b^a)^285:(b^a);
            }
            stack.add(arrLsXsDxs);

        }
        int[] jcmArrYs=(int[]) stack.peek();
        /*
        * 这里得到的结果数组会多一位 就是最后一位 但是最后一位是没有赋值的
        * 为什么会多一位
        * 我的理解为当结果位等于纠错码多一位的时候,我们需要保持位数(如果比他小,后面我们需要补零)
        * 因为抑或始终会少一位,如果的你位数太小,怎么能保证结果码的位数
        * 所以最后我们去掉最后一位就为结果码
        * */
        for(int i=0;i<jcmArrYs.length-1;i++){
            jcmArr[i]=jcmArrYs[i];
        }
        //return jcmArr;
    }
    public int getZh(int zs){
        double a=(double)zs;
        return (int)Math.pow(2,a);
    }
    /*
    * 指数转换为伽罗华域值
    * */
    public int getAlpha(int num){
        int a=1;
        if(num>0){
            for(int i=1;i<=num;i++){
                a=a*2>255?(a*2)^285:a*2;
            }
        }
      return a;
    }
    public int getCount(int num,int ms){
        if(ms==0||ms==num){
            return 1;
        }
        int count=1;
        for(int i=1;i<=ms;i++){
            count=count*(num-i+1);
        }
        for(int i=1;i<=ms;i++){
            count=count/i;
        }
        return count;
    }
    /*(关键)
    * 获取伽罗华域的表   指数为0--254 因为伽罗华域只有255个值1-255
    * @value 表示指数 key表示伽罗华域值
    * 集合方便取值
    * */
    public Map<Integer,Integer> getJlub(){
        Map<Integer,Integer> map=new HashMap<Integer, Integer>();
        for(int i=0;i<255;i++){
            map.put(getAlpha(i),i);
        }
        return map;
    }
    /*
    * 生成多项式方法二:采用深度
    * 思路:先获取 1次 一项式展开式 x+a0  1
    *      在获取2次  二项式展开式(x+a0)(x+a1)=x2+a0^a1x+a0*a1  2
    *      ...
    *      获取n次   n项式展开式就为n-1的展开式乘以x+an-1    n
    *  方法是采用错位相加的办法 如 deep=3 可以得到 deep=2 是的多项式为 x2+3x+2
    *    那么deep=3的多项式为(x2+3x+2)(x+4)
    *                        x3+3x2+2x
    *                     +     4x2+12x+8
     *                     =x3+7x2+14x+8
    * */
    class jcmDxs{
        public int deep;
        public int[]  backDxsArr;
        public int[]  dxsArr;
        public Map<Integer,Integer> map;
        public jcmDxs(){}
        public jcmDxs(int[]  backDxsArr,int deep,Map<Integer,Integer> map){
            this.backDxsArr=backDxsArr;
            this.deep=deep;
            this.map=map;
            jsDxsZks();
        }
        /*
        *计算多项式展开式
        */
        public void jsDxsZks(){
            deep=deep+1;
            if(deep==1){
                dxsArr= new int[]{1, 1};
                return;
            }
            dxsArr=new int[backDxsArr.length+1];
            int a=getAlpha(deep-1);
            dxsArr[0]=1;
            //dxsArr[backDxsArr.length]=a;
            for(int i=1;i<backDxsArr.length+1;i++){
                //int b=(a^dxsArr[i])>256?(a^dxsArr[i])^285:(a^dxsArr[i]);
                int b=(deep-1+map.get(backDxsArr[i-1]))>=255?(deep-1+map.get(backDxsArr[i-1]))%255:(deep-1+map.get(backDxsArr[i-1]));
                b=getAlpha(b);
                if(i<backDxsArr.length){
                     b=((backDxsArr[i]^b)>256)?(backDxsArr[i]^b)^285:(backDxsArr[i]^b);
                }
                dxsArr[i]=b;
            }
        }
        /*
         * 指数转换为伽罗华域值
         * */
        public int getAlpha(int num){
            int a=1;
            if(num>0){
                for(int i=1;i<=num;i++){
                    a=a*2>255?(a*2)^285:a*2;
                }
            }
            return a;
        }
    }
    public static void main(String[] args) {
        makeJcm m=new makeJcm();
        m.makeQrJcm(arrXs2,m.makeDxsDeep(13));
//α0x7 + α87x6 + α229x5 + α146x4 + α149x3 + α238x2 + α102x + α21
        //1  127  122  154  164  11 68 117
    }
}

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值