python 有限域函数库_有限域(4)——程序实现有限域的运算
版權(quán)申明:本文為博主窗戶(Colin Cai)原創(chuàng),歡迎轉(zhuǎn)帖。如要轉(zhuǎn)貼,必須注明原文網(wǎng)址
http://www.cnblogs.com/Colin-Cai/p/9652019.html
作者:窗戶
QQ/微信:6679072
E-mail:6679072@qq.com
前一章,我們知道了使用素域的多項(xiàng)式環(huán)的商環(huán)構(gòu)造任意的有限域的方法。這一章里,我們就用程序?qū)崿F(xiàn)任意有限域里的運(yùn)算。
我在這里還是同第一章一樣,選擇用Scheme來(lái)描述。
數(shù)據(jù)表示
首先,我們需要的一個(gè)參數(shù)就是域的特征,記為?p
根據(jù)上章分析,我們還需要一個(gè)不可分多項(xiàng)式,稱(chēng)為生成多項(xiàng)式,記為 poly
上一章還有一個(gè)重要結(jié)論是,如果poly的次數(shù)是n, 那么所有的次數(shù)小于n的多項(xiàng)式共計(jì)pn個(gè),分別屬于不同的商集,除此之外并無(wú)其他商集,那么也就對(duì)應(yīng)著最后的域的元。
所以,我們這里就以這pn個(gè)小于n次的多項(xiàng)式來(lái)代表該域的所有元,這種表示是合理的。
現(xiàn)在,我們來(lái)考慮不可分多項(xiàng)式以及域里每個(gè)元的計(jì)法:
我們用一個(gè)長(zhǎng)度為n+1的list來(lái)記錄生成多項(xiàng)式poly就可以了(n次多項(xiàng)式一共n+1個(gè)系數(shù)),這個(gè)list的第0項(xiàng)、第1項(xiàng)、...第n-1項(xiàng)、第n項(xiàng)分別對(duì)應(yīng)著poly的n次系數(shù)、n-1次系數(shù)、...1次系數(shù)、0次系數(shù)(常數(shù)項(xiàng))。比如,特征2素域下的3次不可分多項(xiàng)式 x3+x+1,記作(1? 0 1 1)。
而對(duì)于每個(gè)域里的元,我們也用上述的寫(xiě)法來(lái)記,只是,我們把這個(gè)多項(xiàng)式補(bǔ)齊成n-1次,沒(méi)有的項(xiàng)系數(shù)都為0,比如在2特征、生成多項(xiàng)式x3+x+1的域下,元[x+1]記為(0 1 1),也就是一個(gè)域下所有的元,記錄成list都是生成多項(xiàng)式的次數(shù)這么長(zhǎng)。
函數(shù)定義
我們?cè)賮?lái)定義函數(shù)接口,我們就這樣去表示有限域里的加減乘除:
(add poly p a b) 代表p特征、生成多項(xiàng)式為poly時(shí),a+b
(sub poly p a b) 代表p特征、生成多項(xiàng)式為poly時(shí),a-b
(mul poly p a b) 代表p特征、生成多項(xiàng)式為poly時(shí),a*b
(div poly p a b) 代表p特征、生成多項(xiàng)式為poly時(shí),a/b
當(dāng)然,除法涉及到求逆,
(inv poly p a) 代表p特征、生成多項(xiàng)式為poly時(shí),a的逆
程序設(shè)計(jì)
有了上述準(zhǔn)備,再來(lái)看第一章的素域里的加減乘除:
;加法
(define (addp p a b)
(if (>= (+ a b) p) (- (+a b) p)
(+a b)
)
)
;減法
(define (subp p a b)
(addp p a (if (zero? b) 0 (-p b)))
)
;乘法
(define (mulp p a b)
(remainder (*a b) p)
)
;求逆
(define (invp p a)
(define (pow n a b)
(cond
((zero?n) a)
((zero? (remainder n 2)) (pow (quotient n 2) a (mulp p b b)))
(else (pow (quotient n 2) (mulp p a b) (mulp p b b)))
)
)
(pow (- p 2) 1a)
)
;除法
(define (divp p a b)
(mulp p a (invp p b))
)
加法和減法很容易做,一個(gè)map,對(duì)應(yīng)的都是相同次數(shù)的項(xiàng)的系數(shù),然后做合并同類(lèi)項(xiàng)即可。
(define (addp p a b)
(if (>= (+ a b) p) (- (+a b) p)
(+a b)
)
)
(define (subp p a b)
(addp p a (if (zero? b) 0 (-p b)))
)
而對(duì)于inv求逆來(lái)說(shuō),因?yàn)閜n階域里,除0之外的所有的元乘法構(gòu)成一個(gè)群,所以任何一個(gè)元的pn-1 次冪就是自己的逆元。
(define (inv poly p a)
(define (pow poly p a n)
(if (zero?n)
(append (make-list (- (length a) 1) 0) '(1)) ;指數(shù)為0的時(shí)候就是1元
(mul poly p a (pow poly p a (- n 1))) ;否則就是a和a的n-1次冪的乘積
)
)
(define (pow-n p n)
(if (zero? n) 1 ;指數(shù)為0的時(shí)候就是1(* p (pow-n p (- n 1))) ;否則就是p和p的n-1次冪的乘積
)
)
(pow poly p a (- (pow-n p (length a)) 2))
)
于是,除法也就順理成章:
(define (div poly p a b)
(mul poly p a (inv poly p b))
)
當(dāng)然,上面的求冪算法是個(gè)效率很差的算法。我們可以改個(gè)對(duì)數(shù)級(jí)的算法,此處不多解釋。理論依據(jù)我之前的文章《RSA簡(jiǎn)介(二)——模冪算法》
于是我們效率高的求逆如下:
(define (inv poly p a)
(define (pow poly p a n)
(define (pow2 n r x)
(cond
((zero?n) r)
((zero? (remainder n 2)) (pow2 (quotient n 2) r (mul poly p x x)))
(else (pow2 (quotient n 2) (mul poly p r x) (mul poly p x x)))
)
)(pow2 n (append (make-list(- (length a) 1) 0) '(1)) a)
)
(define (pow-n p n)
(define (pow2 n r x)
(cond
((zero?n) r)
((zero? (remainder n 2)) (pow2 (quotient n 2) r (*x x)))
(else (pow2 (quotient n 2) (* r x) (*x x)))
)
)
(pow2 n1p)
)
(pow poly p a (- (pow-n p (length a)) 2))
)
關(guān)鍵是乘法,做起來(lái)有些難,對(duì)lisp沒(méi)有太多基礎(chǔ)且不習(xí)慣函數(shù)式編程的人可能很難寫(xiě)出來(lái)。
兩個(gè)元的乘法結(jié)果應(yīng)該是其多項(xiàng)式乘法然后對(duì)生成多項(xiàng)式做帶余除法得到的余數(shù)。
從而,可以先構(gòu)造兩個(gè)函數(shù),一個(gè)函數(shù)是多項(xiàng)式乘法:
(define (poly-mul p a b)
(map (lambda (x) (remainder x p))
(cdr
(foldr
(lambda (x y)
(cons
(+ 1(car y))
(map+(append (make-list (- (length b) (car y) 1) 0) (map (lambda (c) (* c x)) a) (make-list (car y) 0))
(cdr y)
)
)
)
(make-list (+ (length a) (length b)) 0)
b
)
)
)
)
一個(gè)用迭代實(shí)現(xiàn)的帶余除法,如下
(define (division a b)
(define (division-iter a b b_len times)
(cond
((zero? times) a)
(else
(division-iter
(append
(map
(lambda (x y) (modulo (- x (* y (divp p (car a) (car b)))) p))
(cdr (take a b_len))
(cdr b)
)
(drop a b_len)
)
b
b_len
(- times 1)
)
)
)
)
(division-iter a b (length b) (- (length a) (length b) -1))
)
有了上述基礎(chǔ),就可以構(gòu)造乘法,乘法就是
(define (mul poly p a b)
(division
(poly-mul p a b)
poly
)
)
多項(xiàng)式乘法poly-mul的實(shí)現(xiàn)中用到了foldr算子,這個(gè)算子并不是定義在Scheme任何標(biāo)準(zhǔn)中的,獨(dú)屬于racket。不過(guò)這個(gè)算子實(shí)際上就是著名的SICP里的accumulate算子,我也一直很奇怪如此重要的算子為什么不在標(biāo)準(zhǔn)中體現(xiàn)。以下是這個(gè)算子的定義。
(define (foldr op init lst)
(if (null?lst) init
(op (car lst) (foldr op init (cdr lst)))
)
)
測(cè)試
以上,域的加減乘除都有了。
我們可以測(cè)試一下,階最小的不是素域的有限域是4階,特征為2。
特征2素域下的不可分2次多項(xiàng)式只有一個(gè),x2+x+1
(define poly '(1 1 1)) ;生成多項(xiàng)式
(define p 2) ;特征
(define (list-all)
(define (sub1 x)
(foldr (lambda (m n) (if (zero? (apply * n)) (cons m n) (cons (- 1 m) n))) '() x)
)
(define (func2 x y)
(let*((a (car x))
(b (cdr x))
(asum (apply+a))
(bsum (apply+b))
)
(cond
((zero? (+asum bsum)) (cons x y))
((zero?bsum) (func2 (cons (sub1 a) (sub1 b)) (cons x y)))
(else(func2 (cons a (sub1 b)) (cons x y)))
)
)
)
(let ((m (make-list (- (length poly) 1) (- p 1))))
(func2 (cons m m)'())
)
)
(for-each
(lambda (x) (display (string-append
(format"~a+~a=~a ~a-~a=~a ~a*~a=~a"(car x)
(cdr x)
(add p (car x) (cdr x))
(car x)
(cdr x)
(sub p (car x) (cdr x))
(car x)
(cdr x)
(mul poly p (car x) (cdr x))
)
(if (zero? ( foldr + 0(cdr x)))"\n"(format"~a/~a=~a\n"(car x)
(cdr x)
(div poly p (car x) (cdr x))
)
)
)
)
)
(list-all)
)
上面測(cè)試代碼中poly和p可以任意改,這里只以4階域?yàn)闇y(cè)試對(duì)象。
以上運(yùn)行結(jié)果如下:
(0 0)+(0 0)=(0 0) (0 0)-(0 0)=(0 0) (0 0)*(0 0)=(0 0)
(0 0)+(0 1)=(0 1) (0 0)-(0 1)=(0 1) (0 0)*(0 1)=(0 0) (0 0)/(0 1)=(0 0)
(0 0)+(1 0)=(1 0) (0 0)-(1 0)=(1 0) (0 0)*(1 0)=(0 0) (0 0)/(1 0)=(0 0)
(0 0)+(1 1)=(1 1) (0 0)-(1 1)=(1 1) (0 0)*(1 1)=(0 0) (0 0)/(1 1)=(0 0)
(0 1)+(0 0)=(0 1) (0 1)-(0 0)=(0 1) (0 1)*(0 0)=(0 0)
(0 1)+(0 1)=(0 0) (0 1)-(0 1)=(0 0) (0 1)*(0 1)=(0 1) (0 1)/(0 1)=(0 1)
(0 1)+(1 0)=(1 1) (0 1)-(1 0)=(1 1) (0 1)*(1 0)=(1 0) (0 1)/(1 0)=(1 1)
(0 1)+(1 1)=(1 0) (0 1)-(1 1)=(1 0) (0 1)*(1 1)=(1 1) (0 1)/(1 1)=(1 0)
(1 0)+(0 0)=(1 0) (1 0)-(0 0)=(1 0) (1 0)*(0 0)=(0 0)
(1 0)+(0 1)=(1 1) (1 0)-(0 1)=(1 1) (1 0)*(0 1)=(1 0) (1 0)/(0 1)=(1 0)
(1 0)+(1 0)=(0 0) (1 0)-(1 0)=(0 0) (1 0)*(1 0)=(1 1) (1 0)/(1 0)=(0 1)
(1 0)+(1 1)=(0 1) (1 0)-(1 1)=(0 1) (1 0)*(1 1)=(0 1) (1 0)/(1 1)=(1 1)
(1 1)+(0 0)=(1 1) (1 1)-(0 0)=(1 1) (1 1)*(0 0)=(0 0)
(1 1)+(0 1)=(1 0) (1 1)-(0 1)=(1 0) (1 1)*(0 1)=(1 1) (1 1)/(0 1)=(1 1)
(1 1)+(1 0)=(0 1) (1 1)-(1 0)=(0 1) (1 1)*(1 0)=(0 1) (1 1)/(1 0)=(1 0)
(1 1)+(1 1)=(0 0) (1 1)-(1 1)=(0 0) (1 1)*(1 1)=(1 0) (1 1)/(1 1)=(0 1)
總結(jié)
以上是生活随笔為你收集整理的python 有限域函数库_有限域(4)——程序实现有限域的运算的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用MyBatista----上传图像
- 下一篇: python篇---在windows下利