( 注:本部分博客主要结合周老师的PPT以及查找的资料,尝试去解释Reed-Solomon Codes的数学原理和信息论原理,并讨论Reed-Solomon Codes在QR二维码方面的应用。)
其实上文中出现的乘法并不是最方便的,因为要经过多次循环,所以出现了基于对数的乘法,使用伽罗华域巧妙地将乘法变成加法。
我们知道,对于模2来说乘法是非常容易的,只要向左移一位(类似于乘2,就是本身的幂加一),再与100011101(比8bits还多一位的素多项式,类似于素数)进行异或,异或的结果就是对应的多项式的系数,例如:
α^1 = 00000010 α^5 = 00100000 α^9 = 00111010 α^13 = 10000111
α^2 = 00000100 α^6 = 01000000 α^10 = 01110100 α^14 = 00010011
α^3 = 00001000 α^7 = 10000000 α^11 = 11101000 α^15 = 00100110
100011101= 1*x^8+0*x^7+0*x^6+0*x^5+1*x^4+1*x^3+1*x^2+0*x^1+1*x^0,前面我们说过mod(p)可将得出来的结果控制在[0,p-1]内,所以当我们将a^k mod (100011101) = 100011101 - a^k,多项式的四则运算里减法和加法都是异或。
于是我们以此类推,直到a^255 = 0000 0001 结束,我们能够将所有[1,255]中的数表示成伽罗华域的符号,从中可以发现另外一种乘法,比如a^34 * a^8 = a^(34+8) = a^42,接下来我们将a^42转换就可以得到乘积了。
那么我们如何将生成子的幂变成多项式呢,事实上是有表可查的,也可以用Python来生成列表:
table = [0]*512 m_table = [0]*256 def tables(prim = 0x11B): x = 1; //g^0 for i in range(0,255): table[i] = x m_table[x] = i x<<1 if x & 0x100 : #最高指数已经到了8,需要异或上prim x ^= prim #用到了前面说到的乘法技巧
对于逆元表,我们也可以用Python描述。若a和b互为逆元,则有a*b = e。用生成元表示为:a^n* a^m = e = 1。又因为e = a^0 = a^255,所以g^k * g(255-k) = g^(k + 255 -k) = e。于是g^k 和 g^(255-k)互为逆元。对于多项式值val,求其逆元。可以先求val对应的g幂次是多少。即g的多少次方等于val。可以通过反向表查询, 设为k。那么其逆元的幂次为255-k。此时再通过正向表查询即可。实现代码如下:
inverse_table = [0]*256 def inverseTable(table, m_table): for i in range(1,255): #0没有逆元,所以从1开始 k = m_table[i]; k = 255 - k; inverse_table[i] = table[k]
接下来我们直接可以求乘法啦,炒鸡简单的是不是!
def table_mul(x,y): if x==0 or y==0: return 0 return table[m_table[x] + m_table[y]]好滴明天终于可以更除法了~