關於一種求最大公約數的算法的分析與證明

問題:請編寫一個方法,功能是實現傳入兩個正整數,返回他們的最大公約數

public static int math(int a, int b) {

...

}

 

分析: 關於這道題的算法有多種,我們今天只研究下面這種算法:

1    public static int math(int a, int b) {

2       int hold = 0;

3       while (b != 0) {

4           hold = a % b;

5           a = b;

6           b = hold;

7       }

8       return a;

9    }

 

 

初看這個解法,你可能會一頭霧水。再看看,更是不知所云。甚至懷疑這樣算是不是可 以得到正確結果,但經過測試你會發現的確可以得到正確結果,這究竟是爲什麼呢?讓我們 來分析一下這個算法,爲了便於敘述,把行號加上:

 

第 1 行,程序調用這個方法時會傳入兩個正整數 a 和 b

第 2 行,聲明一個 int 類型的變量 hold 並賦初值 0;第 3-7 行是一個 while 循環,循環條件是 b!=0;

第 4 行,用 hold 來保存 a%b 的結果

第 5 行,把 b 的值賦給 a

第 6 行,把 hold 的值賦給 b

若 b 不爲 0,則進行下一次循環,直到 b=0 時停止循環

最後第 8 行把 a 的值返回。

 

首先我們假設程序只進行一次循環,也就是說:方法傳入 a 和 b 時

第 4 行,hold=a%b=0;

第 5 行,a=b;

第 6 行,b=hold=0;再進行第 3 行判斷循環停止

第 8 行,返回 a 的值,也就是第 5 行中方法開始時傳入的 b 的值,這說明: 如果 a%b=0 那麼 a 和 b 的最大公約數就爲 b,

這點好理解,a%b=0 也就是說 a 能被 b 整除,那當然 a 和 b 的最大公約數就是 b 了。 關鍵是如果不是進行一次,而是進行多次循環呢?

爲了便與理解,我把上面的程序改爲遞歸算法:

1    public static int math1(int a, int b) {

2       if (b == 0) {

3           return a;

4       }

5       int hold = a % b;

6       a = b;

7       b = hold;

8       return math1(a, b);

9    }

 

第 1 行,程序調用這個方法時傳入兩個正整數 a 和 b

第 2-4 行,如果 b 等於 0 返回 a 的值

第 5 行,聲明一個 int 類型的變量 hold 保存 a%b 的結果

第 6 行,把 b 的值賦給 a

第 7 行,把 hold 的值賦給 b

第 8 行,遞歸調用,直到 b 的值爲 0 時返回 a 的值

最後第 8 行把 a 的值返回。

 

在首次調用這個方法傳入 a 和 b 的值時第 3 行肯定不會執行,而是執行 5-8 行的代碼, 由第 8行,我們可以看出程序的意思是 a和 b的最大公約數與 b和 a%b 的最大公約數相同。

 

假設程序進行三次遞歸:

 

第一次程序傳入 a 和 b,

35

30

第二次相當於傳入 b 和 a%b,

30

5

第三次相當於傳入 a%b 和 0;(上次中 b%(a%b)=0)

5

0

最後程序返回 a%b。

5

 

 

由此我們可以得到如下兩個命題:

命題一:a 和 b 的最大公約數與 b 和 a%b 的最大公約數相同;

命題二:如果 b%(a%b)=0,那麼 a 和 b 的最大公約數爲 a%b,(其中 a,b 都爲正整數,且 a%b!=0)。 

 

如果能證明這兩個命題,則上面的算法也就不難理解了:因爲程序實際上一直在運用命題一反覆進行遞歸調用,只是在最後兩次時運用命題二,得出最後結果。

 

我們先看命題一:a 和 b 的最大公約數與 b 和 a%b 的最大公約數相同。 證明:由於 a%b!=0 則 a!=b,當 a<b 時 a%b=a,命題自然成立;

當 a>b  時可設 a 和 b 的最大公約數爲 x;

a=mx,b=nx,其中 m 和 n 爲正整數且 m 與 n 互質(除 1 之外再無其它公因數) 則可設:a%b=(m-kn)x,其中 k 爲正整數

這說明:b 和 a%b 有公因數 x,下面證明 n 與 m-kn 互質 假設 n 與 m-kn 有公因數 y,y 爲正整數且 y 不等於 1 則可設:n=py,m-kn=qy,其中 p 和 q 爲正整數 那麼:m-kn=m-kpy=qy

可得:m=kpy+qy=(kp+q)y

這說明 m 和 n 有公因數 y,與 m 和 n 互質相矛盾,故 n 與 m-kn 互質 由此得 b 和 a%b 的最大公約數也爲x,命題一得證。

 

再看命題二:如果 b%(a%b)=0,那麼 a 和 b 的最大公約數爲 a%b

爲了便於證明我們修改一下這個命題:

已知:m 爲正整數,a=mb+x(即 a%b=x),b 能被 x 整除(即 b%x=b%(a%b)=0),

求證:a 和 b 的最大公約數爲 x(即 a%b) 證明:因爲 b 能被 x 整除,故可設

b=nx,(其中 n 爲正整數)

則:

a=mb+x

=mnx+x

=(mn+1)x

所以:

a 也能被 x 整除 那麼:

a 和 b 的最大公約數一定是 x 的倍數,假設爲 kx,其中 k 爲正整數 則可設:

a=pkx,b=qkx,其中 p 和 q 都爲正整數

那麼:

a=mb+x

=mqkx+x

=(mqk+1)x=pkx

故:

mqk+1=pk

解出 k 得:

k=1/(p-mq)

由於:其中 m、p、q、k 都爲正整數故:k 的值只能爲 1

所以:a 和 b 的最大公約數爲 x,命題二得證。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章