笔记】二维码中的 Reed"/>
【笔记】二维码中的 Reed
如题。。因为看了某针的二维码视频,所以想试试实现自己写个,于是就有了这篇文章。
这里主要研究的是二维码的纠错码。使用语言为Javascript,所有代码均可在浏览器直接运行。
模二除法
因为二维码的编码是在伽罗瓦域中进行的,所以需要大量用到异或和模二乘法。异或很简单,但模二乘法就很复杂了,这里先实现下模二乘法的第二部取余。
模二除法的算法原理参考于模2除法(CRC校验码计算):
1 0 1 1 //商
---------------
1 1 1 1 0 0 0 //被除数,注意首位为1
1 1 0 1 //被除数首位为1,除以除数
---------------0 1 0 0 0 0 //余数去除首位,作为新的被除数0 0 0 0 //被除数首位为0,除以0
---------------1 0 0 0 0 //余数去除首位,作为新的被除数1 1 0 1 //被除数首位为1,除以除数
---------------1 0 1 0 //余数去除首位,作为新的被除数1 1 0 1 //被除数首位为1,除以除数
---------------1 1 1 //余数,此时余数位数少于除数,不能继续除了
看计算过程可以得知,模二除法就是看除的时候某一位是不是1,如果是1就用被除数和除数异或,商1,然后看下一位。
我写的算法和上述有些不同,我是看在某一位的时候用被除数和除数做异或运算后被除数是否变小,如果变小则商一。这个算法其实和最简单的竖列除法差不多,都是尽可能的让被除数变小,待会的多项式除法我会用这个思路。光说可能没那么容易理解,上代码:
function mod_div(a,b){ori = b;while(a > b){b <<= 1;}let ans = 0;while(b >= ori){ans <<= 1;if((a ^ b) < a){a ^= b;ans += 1;}b >>= 1;}return a;
}
在算法中,结果的商也被求出来了,在while
结束时的ans
即使商,不过由于我们只关心余数,这里就先不管它了。
模二乘法
接下来是模二乘法:
function xor_mul(a,b){let ans = 0;while(b > 0){if(b&1){ans ^= a;}b >>= 1;a <<= 1;//console.log(ans)}return ans;
}
算法和快速乘法差不多,这里就不多解释了。
伽罗瓦域中的模二乘法(?)
function mod_mul(a, b, p){return mod_div(xor_mul(a, b),p);
}
有了上面的算法,就可以表示出模二乘法了。其中的p是事先设定好的数值,在视频中这个数是0b1011,也就是11 。
接下来验证我们的算法,很简单,我们试着输出一张GF(2^3)的完整乘法表,然后和视频中对照一下就知道算法正确不正确了:
mod_div_2 = [];
var i = 0;
for(i=0;i<8;++i){mod_div_2[i] = [0,];
}table = '';
for(i=0;i<8;i++){for(j=0;j<8;j++){tmp = mod_mul(i, j, 11);table += tmp;table += ' ';mod_div_2[tmp][i] = j;}table += '\n';
}
console.log('-----table-----');
console.log(table);
console.log('-----table2-----');
console.log(mod_div_2);
输出结果:
-----table-----
0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7
0 2 4 6 3 1 7 5
0 3 6 5 7 4 1 2
0 4 3 7 6
更多推荐
【笔记】二维码中的 Reed
发布评论