Java算法之非遞歸計算兩個數的最大公約數和最小公倍數

目錄

一、最大公約數和最小公倍數的概念

1.1、最大公約數:

1.2、求解最大公約數的方法:

2.1、最小公倍數:

二、Java代碼實現

2.1、用輾轉相除法實現:

2.2、用更相減損法實現:

2.3、用質因數分解法(短除法)實現:


一、最大公約數和最小公倍數的概念

1.1、最大公約數:

        最大公因數,也稱最大公約數、最大公因子,指兩個或多個整數共有約數中最大的一個。

1.1.1、最大公約數基本概念:

        如果數a能被數b整除,a就叫做b的倍數,b就叫做a的約數。約數和倍數都表示一個整數與另一個整數的關係,不能單獨存在。如只能說16是某數的倍數,2是某數的約數,而不能孤立地說16是倍數,2是約數。

  "倍"與"倍數"是不同的兩個概念,"倍"是指兩個數相除的商,它可以是整數、小數或者分數。"倍數"只是在數的整除的範圍內,相對於"約數"而言的一個數字的概念,表示的是能被某一個自然數整除的數。

  幾個整數中公有的約數,叫做這幾個數的公約數;其中最大的一個,叫做這幾個數的最大公約數。例如:12、16的公約數有1、2、4,其中最大的一個是4,4是12與16的最大公約數,一般記爲(12,16)=4。12、15、18的最大公約數是3,記爲(12,15,18)=3。

1.2、求解最大公約數的方法:

      求最大公約數有多種方法,常見的有質因數分解法(短除法)、輾轉相除法、更相減損法。

1.2.1、質因數分解法:把每個數分別分解質因數,再把各數中的全部公有質因數提取出來連乘,所得的積就是這幾個數的最大公約數。

例如:求24和60的最大公約數,先分解質因數,得24=2×2×2×3,60=2×2×3×5,24與60的全部公有的質因數是2、2、3,它們的積是2×2×3=12,所以,(24,60)=12。

1.2.2、短除法:短除法求最大公約數,先用這幾個數的公約數連續去除,一直除到所有的商互質爲止,然後把所有的除數連乘起來,所得的積就是這幾個數的最大公約數。

1.2.3、輾轉相除法, 又名歐幾里德算法(Euclidean algorithm),是求最大公約數的一種方法。它的具體做法是:用較小數除較大數,再用出現的餘數(第一餘數)去除除數,再用出現的餘數(第二餘數)去除第一餘數,如此反覆,直到最後餘數是0爲止。如果是求兩個數的最大公約數,那麼最後的除數就是這兩個數的最大公約數。

例如,求(319,377):

∵ 319÷377=0(餘319)

∴(319,377)=(377,319);

∵ 377÷319=1(餘58)

∴(377,319)=(319,58);

∵ 319÷58=5(餘29)

∴ (319,58)=(58,29);

∵ 58÷29=2(餘0)

∴ (58,29)= 29;

∴ (319,377)=29。

1.2.4、更相減損法:也叫更相減損術,是出自《九章算術》的一種求最大公約數的算法,它原本是爲約分而設計的,但它適用於任何需要求最大公約數的場合。

第一步:任意給定兩個正整數;判斷它們是否都是偶數。若是,則用2約簡;若不是則執行第二步。

第二步:以較大的數減較小的數,接着把所得的差與較小的數比較,並以大數減小數。繼續這個操作,直到所得的減數和差相等爲止。

則第一步中約掉的若干個2與第二步中等數的乘積就是所求的最大公約數。

其中所說的“等數”,就是最大公約數。求“等數”的辦法是“更相減損”法。所以更相減損法也叫等值算法。

例如:用更相減損術求98與63的最大公約數。

解:由於63不是偶數,把98和63以大數減小數,並輾轉相減:

98-63=35

63-35=28

35-28=7

28-7=21

21-7=14

14-7=7

所以,98和63的最大公約數等於7。

 

2.1、最小公倍數:

         兩個或多個整數公有的倍數叫做它們的公倍數,其中除0以外最小的一個公倍數就叫做這幾個整數的最小公倍數。

2.1.1、 求解最小公倍數的方法:

        求解最小公倍數的方法有:分解質因數法和公式法(最小公倍數=兩數的乘積/最大公約(因)數)。

2.1.1.1、分解質因數:

        先把這幾個數的質因數寫出來,最小公倍數等於它們所有的質因數的乘積(如果有幾個質因數相同,則比較兩數中哪個數有該質因數的個數較多,乘較多的次數)。

例如:求45和30的最小公倍數。

   45=3*3*5

   30=2*3*5

  不同的質因數是2。5,3是他們兩者都有的質因數,由於45有兩個3,30只有一個3,所以計算最小公倍數的時候乘兩個3.

  最小公倍數等於2*3*3*5=90

又例如:計算36和270的最小公倍數

  36=2*2*3*3

  270=2*3*3*3*5

  不同的質因數是5。2這個質因數在36中比較多,爲兩個,所以乘兩次;3這個質因數在270個比較多,爲三個,所以乘三次。

  最小公倍數等於2*2*3*3*3*5=540

  20和40的最小公倍數是40

以上相關概念描述均摘自百度百科,僅供參考

二、Java代碼實現

2.1、用輾轉相除法實現:

        解題思路: 用較小數除較大數,再用出現的餘數(第一餘數)去除除數,再用出現的餘數(第二餘數)去除第一餘數,如此反覆,直到最後餘數是0爲止。如果是求兩個數的最大公約數,那麼最後的除數就是這兩個數的最大公約數。

import java.util.Scanner;

/**
 * 輾轉相除法求最大公約數,又名歐幾里德算法(Euclidean algorithm)和最小公倍數(公式法:最小公倍數=兩數的乘積/最大公約(因)數)
 */
public class Gcd {
    public static void main(String[] args) {
        System.out.println("請您分別輸入兩個正整數:");
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
        System.out.println(m+"和"+n+"的最大公約數是:"+gcd(m,n));
        System.out.println(m+"和"+n+"的最小公倍數是:"+m*n/gcd(m,n));
    }

    public static int gcd(int dividend,int divisor){   //dividend 被除數,divisor 除數

        if(divisor<dividend){
            dividend = dividend+divisor;
            divisor = dividend-divisor;
            dividend = dividend-divisor;
        }

        if(dividend==divisor) {
            return 1;
        }

        while(dividend%divisor!=0) {
            int temp = dividend%divisor;
            dividend = divisor;
            divisor = temp;
            if(dividend%divisor==0){
                break;
            }
        }

        return divisor;
    }
}

2.2、用更相減損法實現:

解題思路:

       第一步:任意給定兩個正整數;判斷它們是否都是偶數。若是,則用2約簡;若不是則執行第二步。

      第二步:以較大的數減較小的數,接着把所得的差與較小的數比較,並以大數減小數。繼續這個操作,直到所得的減數和差相等爲止。 則第一步中約掉的若干個2與第二步中等數的乘積就是所求的最大公約數。 其中所說的“等數”,就是最大公約數。求“等數”的辦法是“更相減損”法。所以更相減損法也叫等值算法。

import java.util.Scanner;

/**
 *  更相減損法求最大公約數和最小公倍數(公式法:最小公倍數=兩數的乘積/最大公約(因)數)
 */
public class Gcd {
    public static void main(String[] args) {
        System.out.println("請您分別輸入兩個正整數:");
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
        System.out.println(m+"和"+n+"的最大公約數是:"+gcd(m,n));
        System.out.println(m+"和"+n+"的最小公倍數是:"+m*n/gcd(m,n));
    }

    private static int gcd(int m, int n) {
        int count = 0;   //計數器
        while(m%2==0 && n%2==0) {  //第一步
            m /= 2;
            n /= 2;
            count++;
        }
        if(m<n) {    //m 被減數(較大數),n 減數(較小數)
            m = m+n;
            n = m-n;
            m = m-n;
        }

        if(m==n) {
            return 1;
        }

        while(m-n!=n) {  //第二步
            int temp = m-n;
            if(temp!=n){
                if(temp>n) {
                    m = temp;
                }else{
                    m = n;
                    n = temp;
                }
            }
            if(n==temp) {
                break;
            }
        }
        if(count!=0) {
            return 2*count*n;
        }else {
            return n;
        }
    }
}

2.3、用質因數分解法(短除法)實現:

import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;

/**
 * 質因數分解法(短除法)求最大公約數和最小公倍數(公式法:最小公倍數=兩數的乘積/最大公約(因)數)
 */
public class Gcd {
    public static void main(String[] args) {
        System.out.println("請您分別輸入兩個正整數:");
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
        System.out.println(m+"和"+n+"的最大公約數是:"+gcd(m,n));
        System.out.println(m+"和"+n+"的最小公倍數是:"+m*n/gcd(m,n));
    }

    /**
     * 求最大公約數方法
     * @param m
     * @param n
     */
    private static int gcd(int m, int n) {
        //list1集合和list2集合分別存放m和n分解的質因數
        List<Integer> list1 = primeFactor(m);
        List<Integer> list2 = primeFactor(n);
        List<Integer> list3 = new ArrayList<Integer>();  //list3存放m和n分解的質因數中全部公有的質因數
        int product = 1;   //乘積
        for(int i=0;i<list1.size();i++){
            for(int j=0;j<list2.size();j++){
                if(list1.get(i)==list2.get(j)){
                    list3.add(list2.get(j));
                    list2.remove(j);
                    break;
                }
            }
        }
        for(int i=0;i<list3.size();i++){
            product *= list3.get(i);
        }
        return product;
    }

    /**
     * 分解質因數方法
     * @param num
     * @return
     */
    private static List<Integer> primeFactor(int num) {
        List<Integer> list = new ArrayList<Integer>();
        for(int k=2;k<=num;k++) {
            while(num%k==0 && k!=num) {
                num /= k;
                list.add(k);
            }
            if(num==k) {
                list.add(num);
                break;
            }
        }
        return list;
    }
}

驗證結果:

 

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