基于Excel的QR二维码生成工具——原理及算法详解(之三)

上一篇文章中我们讨论了使用工作表函数计算RS码的算法,接下来,我们将讨论生成多项式的计算以及RS码计算的VBA算法。在已经有了工作表函数计算RS码的情况下,还要探讨使用VBA的原因是因为VBA的计算速度比工作表函数快得多。

在开始探讨生成多项式之前,必须要说明的是,在QR码标准GB18284-2000的附录中已经附带了所有在QR计算中可能会需要的生成多项式,甚至不需要的都一并附上了:
这里写图片描述
但是,有意思的是,RS码的生成多项式其实并不止一个,而且QR标准中给出的并不是标准生成多项式。我尝试了使用标准生成多项式所计算的纠错码,将其填充到QR矩阵中后,同样能够正确解码而且能够正确地纠错。因此,如果没有耐心,只想寻求干货的同学可以绕过这一段,而有兴趣的同学可以一起探讨一下,使用不同的生成多项式来创建与QR标准中完全不同的二维码。

我们知道标准生成多项式的公式为:

g(x)=(x+a)(x+a 2 )(x+a 3 )(x+a nk ) 
,从这个公式可以看出来其实这是一个非常典型的递进算法,如果令 nk=v  ,且另上式为 g v (x)  ,那么我们可以看到:
g 1 (x)=(x+a) 
g 2 (x)=(x+a)(x+a 2 )=g 1 (x)(x+a 2 ) 
以至于一般地
g v (x)=g v1 (x)(x+a v ) 

我们可以如同上一节中一样,将上述多项式的计算通过一个表格来实现:

v= x  的幂次 x 0   x 1   x 2   x 3   x 4   x 5  
g 1 (x)  a  的幂次 1 0
乘数 a  的幂次 2 0

上表中使用不同的列代表多项式的不同次数的项,并且将系数写到单元格中,可见第二行表示的就是 g 1 (x)  ,因为这个多项式的 x 0   项系数为 a  的1次幂,而 x 1   项系数为 a  的0次幂,也就是 (x+a)  。同理,“乘数”行表示的多项式就是 (x+a 2 )  了。那么要计算 g 2 (x)  需要用乘数乘以 g 1 (x)  ,在表格中就是用乘数的所有系数分别乘以 g 1 (x)  的所有系数,并且进行恰当的移位:

v= x  的幂次 x 0   x 1   x 2   x 3   x 4   x 5  
g 1 (x)  a  的幂次 1 0
乘数 a  的幂次 2 0
g 1 (x)  乘以2 a  的幂次 3 2
g 1 (x)  乘以0 a  的幂次 1 0
g 2 (x)  a  的幂次 3 26 0

上表中表示了这样的计算,请注意 g 1 (x)  乘以0的结果是向右移位的,这是因为“0”项的次数为1,因此乘以 g 1 (x)  以后会使它的多项式所有项的幂次升高一次,在表格上就表示为右移一位。然后将两次计算的结果相加,就得到了 g 2 (x)  的多项式

同理我们可以用上面的表格计算 g 3 (x)  乃至于 g v (x) 

v= x  的幂次 x 0   x 1   x 2   x 3   x 4   x 5  
g 2 (x)  a  的幂次 3 26 0
乘数 a  的幂次 3 0
g 2 (x)  乘以3 a  的幂次 6 29 3
g 2 (x)  乘以0 a  的幂次 3 26 0
g 3 (x)  a  的幂次 6 201 199 0

在Excel中可以很容易根据上面的表格来构造 g(x)  的计算公式矩阵:
$g(x)$计算

需要注意的是,在上面的算法中表格的最左列是 x  的最低次幂,而在RS计算表格中,最左列是 x  的最高次幂,因此在使用计算结果的时候,需要进行一次倒序,同时还需要将 a  的幂次转化成系数才行

好了,现在我们已经完成了生成多项式的构造,并且探讨了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
发布了15 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Shepherdppz/article/details/78118561
今日推荐