1. 程式人生 > >求最大公約數的演算法

求最大公約數的演算法

【轉】

更相減損術

更相減損術,又稱"等值演算法"

關於約分問題,實質是如何求分子,分母最大公約數的問題。《九章算術》中介紹了這個方法,叫做”更相減損術”,數學家劉徽對此法進行了明確的註解和說明,是一個實用的數學方法。

例:今有九十一分之四十九,問約之得幾何?

我們用(91,49)表示91和49的最大公約數.按劉徽所說,分別列出分子,分母。

“以少減多,更相減損,求其等也,以等數約之,等數約之,即除也,其所以相減者皆等數之重疊,故以等數約之。”

譯文如下:

約分的法則是:若分子、分母均為偶數時,可先被2除,否則,將分子與分母之數列在它處,然後以小數減大數,輾轉相減,求它們的最大公約數,用最大公約數去約簡分子與分母。

其與古希臘歐幾里德所著的《幾何原本》中卷七第一個命題所論的相同。列式如下:

91 49

42 49

42 7

35 7

28 7

21 7

14 7

7  7

這裡得到的7就叫做“等數”,91和49都是這等數的重疊(即倍數),故7為其公約數.而7和7的最大公約數就是7,(7,7)=7,所以(91,49)=(42,7)=(7,7)=7

更相減損術在現代仍有理論意義和實用價值.吳文俊教授說:“在我國,求兩數最大公約數即等數,用更相減損之術,將兩數以小減大累減以得之,如求24與15的等數,其逐步減損如下表所示:(24,15)->(9,15)->(9,6)->(3,6)->(3,3)

每次所得兩數與前兩數有相同的等數,兩數之值逐步減少,因而到有限步後必然獲得相同的兩數,也即所求的等數,其理由不證自明。

這個寓理於算不證自明的方法,是完全構造性與機械化的儘可以據此編成程式上機實施”.吳先生的話不僅說明了此法的理論價值,而且指明學習和研究的方向.

更相減損法很有研究價值,它奠定了我國漸近分數,不定分析,同餘式論和大衍求一術的理論基礎.望能仔細品味。

 

輾轉相除法

輾轉相除法,又名歐幾里德演算法(Euclidean algorithm)乃求兩個正整數之最大公因子的演算法。它是已知最古老的演算法,其可追溯至前300年。它首次出現於歐幾里德的《幾何原本》(第VII卷,命題i和ii)中,而在中國則可以追溯至東漢出現的《九章算術》。它並不需要把二數作質因子分解。

證明:

設兩數為a、b(b<a),求它們最大公約數(a、b)的步驟如下:用b除a,得a=bq......r1(0≤r)。若r1=0,則(a,b)=b;若r1≠0,則再用r1除b,得b=r1q......r2(0≤r2).若r2=0,則(a,b)=r1,若r2≠0,則繼續用r2除r1,……如此下去,直到能整除為止。其最後一個非零餘數即為(a,b)。

輾轉相除法是利用以下性質來確定兩個正整數a和b的最大公因子的:

1.若r是a÷b的餘數,則gcd(a,b)=gcd(b,r)

2.a和其倍數之最大公因子為a。

另一種寫法是:

1.a÷b,令r為所得餘數(0≤r<b)。若r=0,演算法結束;b即為答案。

2.互換:置a←b,b←r,並返回第一步。

求最大公約數的C/C++演算法

//更相減損法

int gcd(int a,int b)
{
    while(a!=b)
    {
       if(a>b)
           a-=b;
       else
           b-=a;
    }
    return a;
}
//輾轉相除法--遞迴

int gcd(int a,int b)
{
    if(b==0)
       return a;
    else
       return gcd(b,a%b);
}
//輾轉相除法--純迴圈

int gcd(int a,int b)
{
    int r;
    while(b!=0)
    {
       r=a%b;
       a=b;
       b=r;
    }
    return a;
}