`
周凡杨
  • 浏览: 235125 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

求最大公约数之四部曲

阅读更多

解法一:

欧几里得算法 ( 又称辗转相除法 )

        题:给定两个正整数 m n ,求它们的最大公约子(即能得到同时整除 m n 的最大正整数)

        解:

          E1.[ 求余数 ] n m 并令 r 为所得余数。(我们将有 0<<r<n

          E2.[ 余数为 0 ] r=0 ,算法结束, n 即为答案

          E3.[ 减少 ] m<-n n<-r ,并返回步骤 E1

 

算法示意图:


  

public int commonValue(int max,int min){

        if(max<0|| min<0){

           System.out.println("输入的两个参数必须为正整数。");

           return -1;

       }

       if(max<min){

            int temp = min;

            min = max;

            max = temp;

       }

       int remainder = max%min;

       while(remainder!=0){

           max = min;

           min = remainder;

           remainder = max%min;

       }
       return min;

    }
 

 

 

引申题:

   求两个线段长度的“最大公共量度”   ,其中心思想就是求最大公约数

 

 

解法二:

解法一中,用到了取模运算。但对于大整数而言,取模运算(其中用到除法)是非常昂贵的开销,有没有办法能够不用取模运算呢?

  分析:如果一个数能够同时整除 x y(x > y) ,则必能同时整除 x-y y; x y 的公约数与 x-y y 的公约数是相同的,其最大公约数也是相同的,即 f(x,y)=f(x-y,y) ,那么就可以不再需要进行大整数的取模运算,而转换成简单得多的大整数的减法。

示例:

  f(42,30)=f(30,12)=f(18,12)=f(12,6)=f(6,6)=f(6,0) = 6

 

public int cv(int max,int min){

        if(max<min)

            return cv(min,max);

        if(min == 0)

            return max; 

        else

            return cv(max-min,min);

    }

 

   优点: 用减法代替除法,可以提高算法的效率。

   缺点: 如果遇到 f(10 000 000 000 000,1) 这类情况(即两数值相差很大),本算法就不如算法一效率高。

 

 

解法三:

更相减损术: 是出自《九章算术》的一种求 最大公约数 算法 ,它原本是为 约分 而设计的,但它适用于任何需要求最大公约数的场合。

第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2 约简;若不是则执行第二步。

第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。

  则第一步中约掉的若干个2 与第二步中等数的乘积就是所求的最大公约数。


该算法的思想是用 2 约简,该算法相比算法二效率有所提高, 那能不能进一步改进算法,想一想该算法只是在两个整数都为偶数的时候用 2 约简,当一个为偶数,一个有奇数时能约简吗?

 

 

private int count = 0;   //计数器,标记用2约简的次数
public int cv2(int max,int min){
		 if(max<min)
			 return cv2(min,max);
		 if(isEven(max)&&isEven(min)){
			 count++;
			 return cv2(max>>1,min>>1);
		 }
		 if(min == max-min){
			 while(count-->0){
			    min = min<<1;
			 }
			 return min;
		 }
		 else
			 return cv2(max-min,min);
	}
	//函数--判断是否是偶数
	public boolean isEven(int i){
		if((i&1) == 0)
			return true;
		return false;
	}
 

解法四:

对于 y x 来说,如果 y = k*y, x = k*x1 。那么有 f(y,x)=k*f(y1 ,x1 ) 。另外,如果 x = p*x1 , 假设 p 是素数,并且 y%p!=0( y 不能被 p 整除 ) ,那么 f(x,y)=f(p*x1, y)=f(x1, y)

同样的为了便于提高运算效率,采用 2 这个素数(乘除运算便于转化成位移运算)。

p = 2

x,y 均为偶数, f(x,y)=2*f(x/2,y/2)=2*f(x>>1,y>>1)

x 为偶数, y 为奇数 ,f(x,y)=f(x/2,y)=f(x>>1,y)

x 为奇数, y 为偶数 ,f(x,y)=f(y,x-y)

那么在 f(x,y)=f(y,x-y) 之后, (x-y) 是一个偶数,下一步定会有除以 2 的操作(即两奇数相减得偶数)。

最坏情况下的时间复杂度是 O(log2 (max(x,y)))

 

f(42,30)=f(42/2,30/2)

          =2 * f(21,15)

          =2 * f(15,21-15)

          =2 * f(15,6)

          =2 * f(15,6/2)

          =2 * f(15,3)

          =2 * f(15-3,3)

          =2 * f(12,3)

          =2 * f(12/2,3)

          =2 * f(6,3)

          =2 * f(6/2,3)

          =2 * f(3,3)

          =2 * f(3,0)

          =2*3

          =6

 

public int cv(int max,int min){

        if(max<min)

            return cv(min,max);

        if(min==0){

            return max;

        }else{

            if(isEven(max)){

               if(isEven(min))

                   return (cv(max>>1,min>>1)<<1);

               else

                   return cv(max>>1,min);

            }else{

               if(isEven(min))

                   return cv(max,min>>1);

               else

                   return cv(min,max-min);

            }

        }

        

    }//函数--判断是否是偶数

public boolean isEven(int i){

if((i&1) == 0)

return true;

return false;

}
 


 

 

  • 大小: 5.8 KB
1
1
分享到:
评论
1 楼 saieuler 2012-09-18  
以前看过,再标记一下

相关推荐

    c++求最大公约数

    有关c++求最大公约数的代码,用的是辗转相除法,很简单的算法过程,主要是求最大公约数

    Verilog求最大公约数

    在这个特定的项目中,我们关注的是如何使用Verilog来实现一个计算两个数最大公约数(Greatest Common Divisor, GCD)的功能。 最大公约数是指能同时整除两个或两个以上整数的最大正整数。求解最大公约数有多种方法...

    用辗转相除法求最大公约数

    根据给定的信息,我们可以提取并总结出以下与“用辗转相除法求最大公约数”相关的知识点: ### 1. 辗转相除法(欧几里得算法)原理 辗转相除法是一种用于计算两个正整数最大公约数(Greatest Common Divisor, GCD...

    基础算法-python求最大公约数和最小公倍数

    python求最大公约数和最小公倍数 #辗转相除法 def gcd(a,b): #最大公约数函数,且最小公倍数 = 两个数相乘 / 最大公约数 if b == 0: return a else: return gcd(b,a%b) print("请输入两个数:") j,k = input()....

    用LabVIEW求最大公约数和最小公倍数

    用LabVIEW求最大公约数和最小公倍数。可以自行选择数据。

    如何用c语言求最大公约数和最小公倍数

    根据提供的文件信息,本文将详细解释如何使用C语言来实现最大公约数(Greatest Common Divisor, GCD)和最小公倍数(Least Common Multiple, LCM)的计算。 ### 最大公约数(GCD) #### 概念 最大公约数是指两个...

    FPGA求最大公约数及最小公倍数verilog

    基于FPGA开发板的两位数求最大公约数和最小公倍数的设计,该设计中利用辗转相减法求得公约数与公倍数,且两个数的数值可通过按键修改,设计灵活可靠。该设计基于vivado开发,并带有testbench文件,方便仿真学习。

    c++代码用递归法求最大公约数

    这个是用递归法来写最大公约数,当然原算法还是欧几里得算法;只不过代码比较简洁

    递归求最大公约数

    C语言编写利用程序递归求最大公约数,递归调用被继承的基类成员函数

    求最大公约数最小公倍数的3种算法的流程图

    辗转相除法,又称欧几里得算法,是最古老的求解最大公约数的方法之一。其基本思想是:对于任意两个正整数a和b(a&gt;b),它们的最大公约数等于a除以b的余数c与b之间的最大公约数。可以表示为GCD(a, b) = GCD(b, a % b)...

    欧几里德算法求最大公约数——C++代码

    欧几里得算法,也称为辗转相除法,是计算两个正整数最大公约数(Greatest Common Divisor, GCD)的一种经典方法。该算法基于以下原理:两个正整数a和b(a&gt;b)的最大公约数等于a除以b的余数c和b之间的最大公约数。...

    求最大公约数

    根据给定的文件信息,我们可以总结出以下关于“求最大公约数”的相关知识点: ### 一、最大公约数(GCD)概念 最大公约数,也称为最大公因数,是指两个或多个整数共有约数中最大的一个。例如,数字8和12的公约数有...

    利用三种算法求最大公约数

    在计算机科学和编程领域,求解最大公约数(Greatest Common Divisor,GCD)是一项基本的任务,它在数学和算法设计中具有广泛的应用。本文将深入探讨三种不同的方法来计算两个整数的最大公约数:分解质因数法、连续...

    C#求最大公约数

    欧几里得算法是求两个正整数最大公约数的最古老且最有效的方法之一。其基本思想是:对于任何两个正整数a和b(a&gt;b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。数学表达式为:GCD(a, b) = GCD(b, a ...

    C语言求最大公约数和最小公倍数算法总结

    C语言求最大公约数和最小公倍数算法总结 C语言中求最大公约数和最小公倍数的各种算法总结,包括辗转相除法和穷举法等。辗转相除法又名欧几里德法,是一种经典的算法,用于计算两个正整数的最大公约数和最小公倍数。...

    对求最大公约数进行白盒测试

    ### 对求最大公约数进行白盒测试的知识点详解 #### 实验目的 - **掌握静态白盒测试方法及一般要求**:了解如何通过分析源代码结构来发现软件缺陷,包括但不限于代码审查、符号执行等技术。 - **掌握白盒测试用例的...

    例3-16求最大公约数.zip

    标题“例3-16求最大公约数.zip”暗示了一个编程示例,旨在实现计算两个或更多整数之间最大公约数(Greatest Common Divisor, GCD)的功能。这个压缩包可能包含一个C++项目或者任何其他编程语言的源代码,如Python、...

    vb求最大公约数和最小公倍数

    VB求最大公约数和最小公倍数 VB语言是Microsoft公司开发的一种高级编程语言,广泛应用于Windows操作系统平台上的应用程序开发。VB语言具有简单易学、开发效率高、应用广泛等特点,深受广大开发者的喜爱。在VB语言中...

    求最大公约数和最小公倍数

    2.编写两个函数,分别求两个整数的最大公约数和最小公倍数

Global site tag (gtag.js) - Google Analytics