伽罗华域, 二维码和CRC

前言
一个钟表表盘上只有0-59的数字.
超出59的数字会被60取余, 即60/60=0.


在数学上, 我们已经习惯了在无线域上随意地加减乘除而不考虑边界.
假如世界不是由无限构成, 而只有3位比特, 0-7这8个数字组成, 又如何保持计算规律的自洽呢?
我们可以仿照表盘的设计, 超出域的部分取余.以加法为例,假如计算5+5,得到10,而10超出了设定的0-7域,故计算10/8=2,让数字回到域内. 但除法却无法计算, 例如5/2=2.5,5和2都是域内数字,而2.5却不伦不类。想要域内计算封闭,就只有改变既有的计算规则了。

伽罗华域拟出了一个全新的有限域计算规则, 在那个域中, 加减乘除规则被修改, 但却让计算结果永远落在有限域中.

伽罗华域(有限域)

伽罗华域因为是有限域, 所以要说明它的边界在哪里.
我们用GF(n^w)来符号化表示伽罗华域.
其中, GF代表伽罗华域, n代表进制数, w代表位数.
以GF(2^3)为例. 它表示了一个边界是000~111的伽罗华域.

伽罗华域中,计算规则被这样修改:

  1. 加减法被删除, 取而代之的是异或 ⨁ \bigoplus 运算.
  2. 乘除法被模二乘除法代替.
  3. 超出有限域的数字(M), 需要被本原多项式P取余. 符号表示为M mod P.
    这三条可保证伽罗华域内的计算结果永远落在域内。
本原多项式

简单来说,本原多项式是可以帮助域外数字回到域内的多项式. 具体操作是与它取余, 即M mod P.
本原多项式是计算得出的, GF(2^3)的其中一个本原表达式是 x 3 + x + 1 x^3+x+1 x3+x+1, 即1011.
一个GF的本原多项式可以有很多, 这里涉及近世代数和数论知识,故按下不表。
总之, 有了本原多项式的帮助, 域内的计算结果就会永远落在域内这几个数字上.

综上,我列举一些例子以直观感受伽罗瓦域的运算规则。
仍以GF(2^3)举例:
加减法→异或运算:十进制 5 + 5 = 5+5= 5+5=二进制 101 ⨁ 101 = 000 = 0 101\bigoplus101=000=0 101101=000=0
乘法→模二乘法: M = 5 ∗ 5 = 101 ∗ 101 = 11001 = 25 , M=5*5=101*101=11001=25, M=55=101101=11001=25超出范围,利用规则3。取本原多项式 P = x 3 + x + 1 P=x^3+x+1 P=x3+x+1,即二进制的 1011 1011 1011,计算 M m o d P = 11001 m o d 1011 = 11 余 100 = 3 余 4 M mod P=11001 mod 1011=11余100=3余4 MmodP=11001mod1011=11100=34,故5*5=4。注意,这里的mod取余数是模二除法的取余,千万不要用四则运算的算法。
除法→模二除法:例子略,乘法里已经给出了一个取余的例子,不取余取模二除法的结果就对了。

CRC校验

我将一串二进制数字10011发送给其他人, 如何验证这个数字传输正确呢?
答案是纠错码.
我在发送10011时会在其末尾再添加一位数, 以表示我传输的数字中1出现的次数是奇数or偶数, 奇1偶0. 因为1出现了3次, 所以在末尾添加1, 连起来就是100111. 如果某一位传输时错误了, 奇偶性就会出错. 这种校验法叫做奇偶校验法.但如果一次性错了两位, 这个办法就失效了.

CRC校验也是基于纠错码的, 但更复杂.
CRC有很多版本. 选择一个版本, 会得到一个除数P和次数n. 在原数据10011后面添加n个0, 然后与P做模二除法, 会得到n位的余数(不够则余数前面补0).
将余数加入10011的后面, 这组数字再与P做模二除法, 就会被整除.
CRC版本越大, 其安全性越高, 否则就会像奇偶校验一样不稳定.但n也会随之变大,,传输数据会变长,相对来说传输效率就变低了。

二维码

二维码张贴在外, 扫描时很容易因为污损, 光线强弱, 导致部分信息扫描错误. 本质上是信息传输错误的问题, 所以二维码也需要类似于CRC的办法.

二维码是伽罗华域的极好应用. 一个字符由两个字节16比特表示, 二维码上信息长度固定, 很符合有限域的设定.

为了简便计算,我们不用16比特,而是由GF(2^3)3比特表示.
000 代表字符 0
001 代表字符 1

111 代表字符 7
GF(2^3)的本原多项式P仍取1011.

如果我想在二维码中保存4个符号: 3417, 并用另外4个符号保存纠错码,那么:

  1. 令固定数 U = ( x − 2 0 ) ( x − 2 1 ) ( x − 2 2 ) ( x − 2 3 ) U=(x-2^0)(x-2^1)(x-2^2)(x-2^3) U=(x20)(x21)(x22)(x23), 将其用四则运算展开得到一个多项式,其中x的系数要用GF(2^3)的规则限制,例如常数项为 M = 1 × 2 × 4 × 8 M=1×2×4×8 M=1×2×4×8,然后计算 M m o d P = 5 M mod P=5 MmodP=5.如此这般,U展开后的结果为 x 4 + 4 x 3 + 7 x 2 + 7 x + 5 x^4+4x^3+7x^2+7x+5 x4+4x3+7x2+7x+5,即14775.
  2. 3417后面以4个0填充, 并做34170000 mod U, 注意所有的四则运算规则都背题换成GF(2^3)的规则. 这个计算非常复杂, 如果掌握了查表法会特别简单. 我举例34170mod14775这一步,可知为了对齐首位3和1,需要上3,再次强调模二乘法 3 × 14775 = 37224 3×14775=37224 3×14775=37224,3与14775中每一个数字做伽罗瓦域模二乘法。接下来34170-37224,减法替换为异或 ⨁ \bigoplus ,得03354。
    一定要记住,所有的四则运算替换为伽罗华域规则。
  3. 计算完毕后,余数是一个4位数字3255。可见每一位数字都在GF(2^3)中.
  4. 将余数接在3417末尾, 组成34173255, 这个数字就是最后的传输码, 它与U的余数为0.
    这里就很像CRC了, 除了我们为多项式系数的运算引入了伽罗华域. 其他与CRC一模一样.
    (实际上CRC相当于引入的是GF(2^1))

神奇的是这套纠错码可以在数据出错时自我修复.
我们符号化前面的数字, 另34173547=M, 求余的商=h.
根据前面的计算, 可知 M = h ∗ U M = h * U M=hU.
又根据U的形式, 可知如果 x = 2 0 , 2 1 , 2 2 , 2 3 x=2^0, 2^1, 2^2, 2^3 x=20,21,22,23, U=0, 所以M=0.
M的多项式形式是 3 x 7 + 4 x 6 + 1 x 5 + 7 x 4 + 3 x 3 + 5 x 2 + 4 x 1 + 7 x 0 3x^7+4x^6+1x^5+7x^4+3x^3+5x^2+4x^1+7x^0 3x7+4x6+1x5+7x4+3x3+5x2+4x1+7x0
带入4个x解, 可得4个值(加减法同样使用伽罗华域规则):
3 + 4 + 1 + 7 + 3 + 2 + 5 + 5 = 0 3+4+1+7+3+2+5+5=0 3+4+1+7+3+2+5+5=0
3 ∗ 2 1 + 4 ∗ 2 1 + 1 ∗ 2 1 + 7 ∗ 2 1 + 3 ∗ 2 1 + 2 ∗ 2 1 + 5 ∗ 2 1 + 5 ∗ 2 1 = 0 3*2^1+4*2^1+1*2^1+7*2^1+3*2^1+2*2^1+5*2^1+5*2^1=0 321+421+121+721+321+221+521+521=0
. . . . = 0 .... =0 ....=0
. . . . = 0 .... =0 ....=0
如果数据正确, 四个值都是0.
否则就是有错误.

假如M误变成了 M ′ = 36573547 M'=36573547 M=36573547, 它在 x 6 x^6 x6 x 5 x^5 x5分别多了2和4.
上述四个公式的结果由于M的错误会变成非零值, 多出的值会显现在非零结果上, 也就是多的值异或运算就是非零值.
设两个出错的位置在 e 1 e_1 e1 e 2 e_2 e2, 分别多了 s 1 s_1 s1 s 2 s_2 s2.
以第一个公式为例:
3 + 6 + 5 + 7 + 3 + 5 + 4 + 7 = 2 = s 1 ∗ ( 2 0 ) e 1 + s 2 ∗ ( 2 0 ) e 2 3+6+5+7+3+5+4+7=2=s_1*(2^0)^{e_1}+s_2*(2^0)^{e_2} 3+6+5+7+3+5+4+7=2=s1(20)e1+s2(20)e2
其余省略…
如此会得到四个四元一次方程, 很容易得到结果.

至于为什么只能纠错两位, 需要了解汉明码相关知识.

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在前端,你可以使用第三方库 `qrcodejs2` 来生成二维码,然后利用 `html-to-canvas` 库将二维码转化为 Canvas 元素,最后通过 `canvas.toDataURL()` 方法将 Canvas 转换成图片的数据 URL,从而实现下载二维码的功能。下面是一个简单的示例代码: 1. 首先,安装 `qrcodejs2` 和 `html-to-canvas` 库: ``` npm install --save qrcodejs2 html-to-canvas ``` 2. 在需要生成和下载二维码的页面中,引入 `qrcodejs2` 和 `html-to-canvas` 库: ```javascript import QRCode from 'qrcodejs2'; import html2canvas from 'html-to-canvas'; ``` 3. 在页面中添加一个容器元素,用于显示生成的二维码: ```html <div id="qrcode"></div> ``` 4. 在 Vue 的 `mounted` 钩子函数中,初始化 `QRCode` 对象,生成二维码: ```javascript mounted() { const qrcode = new QRCode(document.getElementById('qrcode'), { text: 'https://www.example.com', // 二维码内容 width: 256, // 二维码宽度 height: 256, // 二维码高度 colorDark: '#000000', // 二维码颜色 colorLight: '#ffffff', // 二维码背景色 correctLevel: QRCode.CorrectLevel.H, // 容错级别 }); } ``` 在上述代码中,我们通过 `new QRCode()` 方法创建了一个 `QRCode` 对象,并传入二维码的内容、宽度、高度、颜色等参数。最后,将二维码渲染到页面中的 `div` 元素中。 5. 定义一个下载二维码的方法,例如: ```javascript downloadQRCode() { // 获取二维码 Canvas 元素 const qrcode = document.getElementsByClassName('qrcode')[0].getElementsByTagName('canvas')[0]; // 将 Canvas 元素转换成图片 html2canvas(qrcode).then(function (canvas) { // 创建一个 <a> 标签,用于下载图片 const link = document.createElement('a'); link.download = 'qr-code.png'; // 下载的文件名 link.href = canvas.toDataURL(); // 图片的数据 URL document.body.appendChild(link); link.click(); // 触发下载 document.body.removeChild(link); }); } ``` 在上述代码中,我们通过 `document.getElementsByClassName()` 方法获取到生成的二维码 Canvas 元素,然后通过 `html2canvas()` 方法将 Canvas 元素转换成一个新的 Canvas 元素。最后,通过创建一个 `<a>` 标签,将图片的数据 URL 赋值给 `href` 属性,并设置 `download` 属性为要保存的文件名。最后,通过调用 `link.click()` 方法触发下载操作。 6. 在页面中添加一个按钮或其他触发下载的元素,绑定上述方法: ```html <button @click="downloadQRCode">下载二维码</button> ``` 在上述步骤完成之后,你就可以在前端页面中生成二维码,并且通过点击按钮下载生成的二维码图片了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值