第一步:理解伽罗华域(有限域)

伽罗瓦域本质上是一个受限的集合,以及一些数学运算,使得运算的结果仍然在这个集合中。

对于二维码标准来说,要使用位为模数2的算子,字节为模数100011101(本原多项式x**8+x**4+x**3+x**2+1)的算子。这意味着使用GF(2**8),有时写成GF(256)。

GF(256)中的数字都在0到255(含)的范围内。请注意,这也是可以用一个八位比特表示的范围(最大的八位比特是1111_1111,等于255)。

这意味着GF(256)中所有的数学运算都将产生可以用八位字节表示的数字。

第二步:理解伽罗华域内的运算

如前所述,GF(256)包含0到255(含)的数字。GF(256)中的数学运算具有循环性,也就是说,如果在GF(256)中进行数学运算,得到的数字大于255,那么就需要使用求模运算来得到一个仍然在伽罗瓦域中的数字。

在伽罗瓦域中,负数与正数具有相同的值,所以-n=n.换句话说,在伽罗瓦场算术中,始终要使用数字的绝对值。

这就是说,伽罗瓦域内的加法和减法是一回事。伽罗瓦域内的加减法是按正常的方法做加减法,但又要进行模数运算。而由于我们使用的是模2运算(在QR码规范中提到过),这和执行XOR运算是一样的。比如说

1+1=2%2=0

1^1=0

0+1=1%2=1

0^1=1

第三步:用模100011101生成2的幂次

GF(256)中的所有数字都可以用2的幂来表示,具体来说,GF(256)中的所有数字都可以用2**n来表示,其中0 <= n <= 255。然而,如前所述,GF(256)中的所有数字本身必须在0到255的范围内,所以2**8对于伽罗瓦场来说似乎太大了,因为它等于256。

从0到8的2的幂是。
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128
2**8 = 256

二维码规范中说,要使用字节的模100011101运算(其中100011101是二进制数,相当于十进制的285)。这意味着当一个数字为256或更大时,应该用285进行XOR。

换句话说
2**8 = 256 ^ 285 = 29

请注意,当继续计算2**9时,不要取其通常的512值并与285进行XOR(这样做的结果无论如何都是太大了)。相反,由于29=2**8*2,就用上一步计算出的2**8的值。

换句话说
2**9 = 2**8 * 2 = 29 * 2 = 58

使用这个计算方法,GF(256)中的所有数字都可以用2**n表示,其中n是0 <= n <= 255范围内的数字。使用字节模100011101可以保证所有的数值都在0到255的范围内。

由于所有 GF(256) 的值都被表示为 2 的幂,GF(256) 中的所有乘法都可以作为底为2 的指数的加法来执行。

例如,要将16*32相乘,就等于将2**4乘以2**5。正如前一段所解释的,这和2**(4+5)或2**9是一样的。2**9的值已经计算出来了,因此在GF(256)中,用字节模285操作,16*32就是2**9,在上一段中确定等于58。

在加指数时,如果指数变得大于或等于256,只需应用模数255即可。换句话说

2**170 * 2**164 = 2**(170+164) = 2**334 → 2**(334 % 255) = 2**79.

因此,在GF(256)中执行乘法所需要的就是生成所有的2的幂。这些值已经计算出来了,可以在对数反逻辑表中找到。该表使用α符号,其中α=2。QR Code规范在附件A中也使用α符号。

第四步:理解生成多项式

我们在生成纠错码字方面已经取得了很大的进展,但我们还没有达到目的。下一步是了解生成多项式。

如前所述,纠错编码使用多项式长除法。要做到这一点,需要两个多项式。第一个要使用的多项式叫做消息多项式。消息多项式使用数据编码步骤中的数据码字作为其系数。例如,如果数据码字转换为整数,是25,218和35,消息多项式将是25x**2+218x+35。在实践中,标准QR码的实际信息多项式要长得多,但这只是一个例子。

信息多项式将被生成多项式所除。生成多项式是一个多项式,它通过把下面这些项乘起来得到

rs编码Python RS编码流程_抽象代数

其中n是必须生成的纠错码字数(见纠错表)。如上一节所述,α等于2。

可以通过编程创建可能需要的所有的生成多项式。下面举一个例子

纠2个错误的生成多项式

首先,将(x-α**0)和(x-α**1)相乘。

由于x的系数为1,又由于α**0=1,所以可以写成

rs编码Python RS编码流程_编码_02

将第一部分的每项乘以第二部分的每项,得到这样的结果。

rs编码Python RS编码流程_抽象代数_03

注意,这里可以用指数加法来进行乘法。

rs编码Python RS编码流程_rs编码Python_04

结果是:

rs编码Python RS编码流程_线性分组码_05

现在,把同类项组合起来。有两个x1项,所以把它们加在一起。

rs编码Python RS编码流程_rs编码Python_06

请记住,GF(256)中的加法是通过XOR进行的。使用对数反逻辑表将字母转换为它们的整数对应,然后进行XOR。

rs编码Python RS编码流程_抽象代数_07

用阿尔法符号表示,这是

rs编码Python RS编码流程_RS码_08


这就是纠2个错误的生成多项式。

纠3个错误的生成多项式也是一样的计算过程,这里就不算了,有兴趣的可以自己算一下,这里给出答案

rs编码Python RS编码流程_线性分组码_09

rs编码Python RS编码流程_rs编码Python_10

当通过将指数相加进行乘法时,有时可能会导致指数大于或等于256。在这种情况下,在合并同类项之前应用模255。例如

rs编码Python RS编码流程_抽象代数_11

第五步:生成纠错码

假设原始信息为00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000 11101100 00010001 11101100 00010001 11101100 00010001

转换成十进制

32, 91, 11, 120, 209, 114, 220, 77, 67, 64, 236, 17, 236, 17, 236, 17

对应的信息多项式为

rs编码Python RS编码流程_编码_12

假设我们的纠错码能够纠10个错误,使用如下生成多项式

rs编码Python RS编码流程_抽象代数_13

现在是时候将信息多项式除以生成多项式了。除法步骤考虑到了伽罗瓦域的运算。

找出适当的项来乘以生成多项式,乘法的结果应该与消息多项式(在第一个乘法步骤中)或余数(在随后的所有乘法步骤中)的第一项相同。
把结果与信息多项式(在第一个乘法步骤中)或余数(在随后的所有乘法步骤中)异或。
执行这些步骤n次,其中n是数据码字的数量。
注意这些步骤与普通多项式长除法的步骤之间的不同。在乘法步骤之后,我们不做减法,而是执行XOR(在GF(256)中,这是同样的事情)。

更重要的是,两个多项式除法后,会有一个余数。这个余数的系数就是纠错码字。

除法将在下面逐步说明。

完整的消息多项式为

rs编码Python RS编码流程_RS码_14

为了保证在除法过程中,第一项的指数不会变得太小,将消息多项式乘以x**n,其中n是需要的纠错密码字数。在本例中,n为10,为10个纠错密码字,所以将消息多项式乘以x**10,得到。

rs编码Python RS编码流程_RS码_15

生成多项式的第一项也应具有相同的指数,所以乘以x**15得到

rs编码Python RS编码流程_线性分组码_16

现在可以进行重复的除法步骤。除法的步数必须等于信息多项式中的项数。在这种情况下,除法需要16步才能完成。这将导致一个有10个项的余数。这些项将是所需的10个纠错码字。下面给出计算一次的过程,剩下的过程类似

第一步是将生成多项式乘以信息多项式的第一项系数。在这种情况下,前导项是32x**25。由于α符号可以更容易地进行乘法,因此建议将32x**25转换为α符号。根据对数反逻辑表,对于整数值32,α指数为5,因此32=α**5。将生成多项式乘以α**5。

rs编码Python RS编码流程_rs编码Python_17

rs编码Python RS编码流程_RS码_18

第二步把得到的结果与消息多项式异或

rs编码Python RS编码流程_RS码_19

结果是

rs编码Python RS编码流程_线性分组码_20

这就消掉了第一项,下面就是消掉89这一项,这里就不算了

通过16次计算,最终的得到的结果为

rs编码Python RS编码流程_抽象代数_21

纠错码字为

rs编码Python RS编码流程_线性分组码_22

把它添加在信息码字后面即可