在上一篇文章中我们讨论了使用工作表函数计算RS码的算法,接下来,我们将讨论生成多项式的计算以及RS码计算的VBA算法。在已经有了工作表函数计算RS码的情况下,还要探讨使用VBA的原因是因为VBA的计算速度比工作表函数快得多。
在开始探讨生成多项式之前,必须要说明的是,在QR码标准GB18284-2000的附录中已经附带了所有在QR计算中可能会需要的生成多项式,甚至不需要的都一并附上了:
但是,有意思的是,RS码的生成多项式其实并不止一个,而且QR标准中给出的并不是标准生成多项式。我尝试了使用标准生成多项式所计算的纠错码,将其填充到QR矩阵中后,同样能够正确解码而且能够正确地纠错。因此,如果没有耐心,只想寻求干货的同学可以绕过这一段,而有兴趣的同学可以一起探讨一下,使用不同的生成多项式来创建与QR标准中完全不同的二维码。
我们知道标准生成多项式的公式为:
我们可以如同上一节中一样,将上述多项式的计算通过一个表格来实现:
v= | x 的幂次 | x 1 | x 2 | x 3 | x 4 | x 5 | |
---|---|---|---|---|---|---|---|
g 1 (x) | a 的幂次 | 1 | 0 | ||||
乘数 | 2 | 0 |
上表中使用不同的列代表多项式的不同次数的项,并且将系数写到单元格中,可见第二行表示的就是
g 1 (x)
,因为这个多项式的
x 0
项系数为
a
的1次幂,而
v= | x 的幂次 | x 1 | x 2 | x 3 | x 4 | x 5 | |
---|---|---|---|---|---|---|---|
g 1 (x) | a 的幂次 | 1 | 0 | ||||
乘数 | 2 | 0 | |||||
g 1 (x) 乘以2 | a 的幂次 | 3 | 2 | ||||
a 的幂次 | 1 | 0 | |||||
a 的幂次 | 3 | 26 | 0 |
上表中表示了这样的计算,请注意
同理我们可以用上面的表格计算 g 3 (x) 乃至于 g v (x)
v= | x 的幂次 | x 1 | x 2 | x 3 | x 4 | x 5 | |
---|---|---|---|---|---|---|---|
g 2 (x) | a 的幂次 | 3 | 26 | 0 | |||
乘数 | 3 | 0 | |||||
g 2 (x) 乘以3 | a 的幂次 | 6 | 29 | 3 | |||
a 的幂次 | 3 | 26 | 0 | ||||
a 的幂次 | 6 | 201 | 199 | 0 |
在Excel中可以很容易根据上面的表格来构造
需要注意的是,在上面的算法中表格的最左列是
x
的最低次幂,而在RS计算表格中,最左列是
好了,现在我们已经完成了生成多项式的构造,并且探讨了RS码的表格式计算算法。已经完全可以开始进行QR的制作了么?不,没那么简单,使用工作表函数的RS码在进行小规模计算时,计算速度是完全可以胜任的,但是,如果填充的是高版本的QR码,计算量就非常可观了。通常情况下,一个QR码需要对长达上百位的数据码计算30个纠错码,并且因为QR的分段设计,同样的纠错码计算需要重复几十次,这样就导致计算表十分庞大,计算次数达到上百万次。我验证了一下,这样的表格在我的电脑上需要大约25秒才能完成计算,不具备实用性。因此,下面的VBA代码被用来实现同样的RS计算功能,但结果可以瞬间得到:
Private Function ECCALC(dataWords, N, k, gp)
' function that calculates error correction code of the input code words by generate polynomial
' codewords as first argument is the code word for which EC code is calculated
' n as second argument total number of code words
' k as third argument defines the number of data code words, thus n-k is the number of error correction code words
' output of the function is also defined as an array that contains the error correction code
' the error correction code is calculated on the galois field with primitive polynomial= x^8+x^4+x^3+x^2+1=0
'
Dim gpWords(), cWords(), dWords(), prod() As Long
ReDim gpWords(N - k), cWords(N), dWords(N), prod(N - k)
Dim divider As Long
Dim num, EC As Variant
Dim i,j As Long
With Sheets("RS Calc")
For i = 0 To 254
GF(i) = .Cells(7, i + 6)
GFP(i) = .Cells(8, i + 6)
Next
End With
'read genpoly
i = 0
For Each num In dataWords
If IsNumeric(num) Then
cWords(i) = num
i = i + 1
End If
Next
i = 0
For Each num In gp
If IsNumeric(num) Then
gpWords(i) = num
i = i + 1
End If
Next
'RS calculation starts
For i = 0 To k - 1
divider = cWords(0)
For j = 0 To N - 2 'calculate next code words by multiply genopoly with divider, and substract code word
If j < N - k And divider <> 0 Then
num = cWords(j + 1) Xor nGfMult(divider, gpWords(j + 1))
Else
num = cWords(j + 1) Xor 0
End If
cWords(j) = num
Next
Next
ECCALC = cWords
End Function