Try   HackMD

擴展歐基里德算法 (Extended Euclidean algorithm)

歐基里德算法

歐基里德算法又稱輾轉相除法,是計算兩個整數的最大公因數(Greatest Common Divisor, GCD)的方法。

有兩個數字

a,b,令
p=gcd(a,b)
,那麼一定存在兩個正整數
n,mR
使得

a=np,b=mp

那麼如果要求

p,我們可以不斷讓
a,b
互減,最後就會剩下
p

下圖是從維基百科上抓來的,兩線段分別表示
252
105
,每個單位為其最大公因數
21

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

可以發現到,當我們重複將較大的一方扣除較小的一方,直到其中一方為

0 時,剩下的就會剛好是最大公因數
p

從這裡我們可以發現到,最大公因數實際上有這樣的性質:

gcd(a,b)={gcd(ab,b)a>bgcd(ba,a)a<b

不過實際上我們也不需要做那麼多次減法,因為我們總是會減到直到不能再減

  • 假設
    a>b
    ,那麼
    ab
    的次數就是
    a/b
    ,而這最後的
    a
    其實就是
    a%b
  • 假設
    a<b
    ,那麼
    ba
    的次數就是
    b/a
    ,而這最後的
    b
    其實就是
    b%a

附註:

為下高斯符號,也就是向下取整
舉例來說:
3.14=3,4.9=4

附註: 雖然沒有提到

a=b 的情況,不過在
a=b
時無論放在
a>b
的作法或是
a<b
的做法也都會是正確的

也就是說:

gcd(a,b)={gcd(a%b,b)a>bgcd(b%a,a)a<b

換個方法敘述
已知

a/b=qr

a=qb+rgcd(a,b)=gcd(qb+r,b)=gcd(r,b)=gcd(a%b,b)

已知

b/a=qr

b=qa+rgcd(a,b)=gcd(qa+r,a)=gcd(r,a)=gcd(b%a,a)

在實作上,可以透過

gcd(a,b)=gcd(b,a%b) 來簡寫
如果
a<b
的話,因為
gcd(b,a%b)
會將兩者交換,因此下一次計算
gcd
時就會計算到
gcd(a,b%a)

def gcd(a, b): if(b == 0): return a return gcd(b, a%b)

擴展歐基里德算法

擴展歐基里德算法的命題如下:

已知

a,bZ,必定存在
x,y
使得貝祖定理成立
ax+by=gcd(a,b)

x,y
分別為何

根據命題可得

ax1+by1=gcd(a,b)bx2+(a%b)y2=gcd(b,a%b)

又因為

gcd(a,b)=gcd(b,a%b)

因此

ax1+by1=bx2+(a%b)y2=bx2+(aa/bb)y2

整理式子後可以得到

ax1+by1=ay2+b(x2a/by2)

因此

{x1=y2y1=x2a/by2

因此,由於

gcd(a,b)=gcd(b,a%b),我們可以將原問題轉換成等價的新問題,並且新問題得出來的
x,y
可以幫助我們得到原問題的
x,y

如此一來就可以實作出擴展歐基里德算法囉!

補充: 在

b=0 的情況下我們知道
a=1×a+0×b
,因此回傳
(x,y)=(1,0)

def exd_gcd(a, b): if(b == 0): return 1, 0 else: x, y = exd_gcd(b, a%b) return y, x-(a//b)*y
tags: Crypto