两个数最大公约数几种算法

解法一:
欧几里得辗转相除法:
f(x,y) = GCD(x,y), 取k = x / y, b = x % y,则:x = k*y + b;
如果一个数能整除x,y,则它也能整除b,y; 而且能整除b,y的数必能整除x,y,即x,y和b,y的公约数是相同的,其最大公约数也是相同的,即f(x,y) = f(y ,x % y) (x>=y>0)

*就是把上一轮有余数的除法计算中, 除数变为下一轮计算的被除数, 余数变为下一轮计算的除数, 一直这样计算下去, 直到最后一次计算余数为零, 在最后一轮计算中的被除数,即为所求的最大公约数。

递归

package lq.ithyl.basis;

import java.util.Scanner;

public class Zdg_1 {

public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
int a=sc.nextInt();
int b=sc.nextInt();
int s=new Zdg().gcd(a, b);
    System.out.println(s);
    }
        int gcd(int a,int b){
            if(b==0){
            return a;
            }else{
                return gcd(b,a%b);
            }
        }
}

非递归

package lq.ithyl.basis;

import java.util.Scanner;

public class Zdg_2 {

    public static void main(String[] args) {
    Scanner sc =new Scanner(System.in);
    int a=sc.nextInt();
    int b=sc.nextInt();
    int s=new Zdg_2().gcd(a, b);
        System.out.println(s);
        }
            int gcd(int a,int b){

                int temp = a;  
                while(b>0){  
                    a = b;  
                    b = temp % b;  
                }  
                return a;
            }
    }

解法二:
分析:
对于x,y,如果y = k * y1,x = k * x1,则f(y,x) = K*f(x1,y1);
如果x = p * x1, 假设p是素数,且 y % p != 0 ,即y不能被p整除,则f(x,y) = f(x1,y).
可以利用上面两点进行改进。因为2是素数,同时对于二进制表示的大整数而言可以很容易的将除以2和乘以2的算法转换为移位运算,从而避免大整数除法。
可以充分利用2进行分析:
若x,y都为偶数(2肯定是公约数),则f(x,y) = 2*f(x / 2,y / 2) = 2*f(x>>1,y>>1);
若x为偶数,y为奇数(2肯定不是公约数),则f(x,y) = f(x / 2, y / 2) = f(x>>1, y)
若x为奇数,y为偶数2肯定不是公约数),则f(x,y)= f(x, y / 2) = f(x, y>>1)
若x,y都为奇数(2肯定不是公约数),则f(x,y) = f(y, x-y) (x-y肯定为偶数) = f(y, (x-y)/2)
package lq.ithyl.basis;

    import java.util.Scanner;

    public class Zdg_3 {

        public static void main(String[] args) {
        Scanner sc =new Scanner(System.in);
        int a=sc.nextInt();
        int b=sc.nextInt();
        int s=new Zdg_3().gcd(a, b);
            System.out.println(s);
            }
                int gcd(int a,int b){

                    //如果a < b  
                    if(a < b){  
                        return gcd(b,a);  
                    }  
                    if(b == 0){  
                        return a;  
                    }  
                    //若x,y都为偶数  
                    if(IsEvenOdd(a) == 1 && IsEvenOdd(b) == 1){  
                        return 2 * gcd(a>>1,b>>1);  
                    }  
                    //若x,y都为奇数  
                    else if(IsEvenOdd(a) == 0 && IsEvenOdd(b) == 0){  
                        return gcd(b,a-b);  
                    }  
                    //若x是偶数y是奇数  
                    else if(IsEvenOdd(a) == 1 && IsEvenOdd(b) == 0){  
                        return gcd(a>>1,b);  
                    }  
                    //若x是奇数y是偶数  
                    else{  
                        return gcd(a,b>>1);  
                    } 

                }
                //判断奇偶性  
                int IsEvenOdd(int n){  
                    if(n % 2 == 0){  
                        return 1;  
                    }  
                    else{  
                        return 0;  
                    } 
        }
}

三:
在解法一中我们用到了取模运算。在大整数中取模运算(涉及到除法运算)是非常高贵的开销。
我们想想避免用取模运算。
类似前面的分析,一个数能整除x,y则必能同时整除x - y,y。能同时整除x - y,y 则必能同时整除x,y。即x,y的公约数和x-y,y的公约数是一样的,其最大公约数也是一样的。
package lq.ithyl.basis;

    import java.util.Scanner;

    public class Zdg_4 {

        public static void main(String[] args) {
        Scanner sc =new Scanner(System.in);
        int a=sc.nextInt();
        int b=sc.nextInt();
        int s=new Zdg_4().gcd(a, b);
            System.out.println(s);
            }
                int gcd(int a,int b){

                    //如果a < b  
                    if(a < b){  
                        return gcd(b,a);  
                    }  
                    if(b == 0){  
                        return a;  
                    }  
                    else{  
                        return gcd(a - b,b);  
                    }  

                }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值