求两个数字的最大公约数-Python实现,三种方法效率比较,包含质数打印质数的方法

今天面试,遇到面试官询求最大公约数。小学就学过的奥数题,居然忘了!只好回答分解质因数再求解!

回来果断复习下,常用方法辗转相除法更相减损法小学奥数都学过,很简单,就不细说了,忘了的话可以百度:http://baike.baidu.com/link?url=Ba106RbHkMjZm3rolmCHEEFt3eDkVbngcReykcqt4Wv0dbTI_0ZmTDE5b0X-xWFx

以下是代码实现,这两种方法,还有常规的分解因式,顺便比较了一下效率,其中分解因式用了两种方法来求取小于该数字的所有质数,:

 

#coding:utf-8
import time
#辗转相除法:
def commonDivisor1(num1,num2):
    if num1 < num2:
        temp = num1
        num1 = num2
        num2 = temp
         
    if  num1%num2 ==0:
        return num2
    else:
        num2 = num1%num2
        return commonDivisor1(num1,num2)

#更相减损法
def commonDivisor2(num1,num2):    
    if num1==num2:return num1
    elif num1 < num2:
        temp = num1
        num1 = num2
        num2 = temp
    if num1 - num2 == num2:
        return num2
    else:
        temp = num1 
        num1 = num2
        num2 = temp - num2
        #print (num1,' ', num2)
        return commonDivisor2(num1,num2)

#分解质因数,之后求解
def commonDivisor3(num1,num2):
    if num1==num2:return num1
    elif num1 < num2:
        temp = num1
        num1 = num2
        num2 = temp  
    #求小于较小数字的所有素数   
    primeNum = getPrimeNumber1(num2)
    #print (primeNum)
    #对较小的数字分解质因数,并将质因数保存在l2中
    l2 = []
    result = 1 
    while num2 != 1:
        for i in primeNum:
            if num2 % i !=0:
                continue
            else:
                l2.append(i)
                num2 = num2 / i 
    #print ('l2: ',l2)
    #使用较大数字去除较小数字的质因数,看大数字中包含了哪些较小数字的质因数。
    #将大数字也包含的相同的质因数相乘返回结果,即最大公约数
    for i in l2:
        if num1 % i == 0:
            result = result*i
            num1 = num1/i
    return result

#分解质因数,之后求解
def commonDivisor4(num1,num2):
    if num1==num2:return num1
    elif num1 < num2:
        temp = num1
        num1 = num2
        num2 = temp  
    #求小于较小数字的所有素数   
    primeNum = getPrimeNumber2(num2)
    #print (primeNum)
    #对较小的数字分解质因数,并将质因数保存在l2中
    l2 = []
    result = 1 
    while num2 != 1:
        for i in primeNum:
            if num2 % i !=0:
                continue
            else:
                l2.append(i)
                num2 = num2 / i 
    #print ('l2: ',l2)
    #使用较大数字去除较小数字的质因数,看大数字中包含了哪些较小数字的质因数。
    #将大数字也包含的相同的质因数相乘返回结果,即最大公约数
    for i in l2:
        if num1 % i == 0:
            result = result*i
            num1 = num1/i
    return result

#列出小于num的所有奇数,首先去除可以被2整除的,再去除可以被3整除的,再去除可以被5整除的,以此类推...           
def getPrimeNumber1(num):
    l = [2]
    for i in range(3,num+1,2):
        l.append(i)
    j = min(l)
    while not j == l[-1]:
        for k in l:
            if (k%j==0) and k != j:
                #print ('remove: ',k)
                l.remove(k)
        #print (l,' ',j)
        j = l[l.index(j)+1]
    return l

#用生成器和filter求num以内的所有质数
def getPrimeNumber2(num):
    l=[]
    for n in primes():
        if n < num:
            l.append(n)
        else:
            break
    return l

#创建打印奇数的生成器
def _odd_iter():
    n = 1
    while True:
        n = n + 2
        yield n

#创建过滤条件,即过滤掉可以被列表中下一个数字整除的数字,留下不可以被这个数整除的,即留下质数
def _not_divisible(n):
    return lambda x: x % n > 0

#不断迭代生成列表,根据规则过滤掉列表中元素,留下质数
def primes():
    yield 2
    it = _odd_iter() # 初始序列
    while True:
        n = next(it) # 返回序列的第一个数
        yield n
        it = filter(_not_divisible(n), it) # 构造新序列
  
time1 = time.clock()
print (commonDivisor1(12355,525))
time2 = time.clock()
print (commonDivisor2(12355,525))
time3 = time.clock()
print (commonDivisor3(12355,525))
time4 = time.clock()
print (commonDivisor4(12355,525))
time5 = time.clock()

print ('辗转相除法用时: ', (time2-time1)*1000,'')
print ('更相减损法用时: ', (time3-time2)*1000,'')
print ('分解质因数法用时(用列表求质数): ', (time4-time3)*1000,'')
print ('分解质因数法用时(用生成器求质数): ', (time5-time4)*1000,'')

 

 

 

 测试结果:

随便测试两个数字,发现辗转相除法明显是最快的,原因也很明显,计算次数明显比更相减损法少,传统分解因式方法,那效率自然不用说了。

35
35
35
35
辗转相除法用时:  0.014617272401167485 秒
更相减损法用时:  0.15565419800162134 秒
分解质因数法用时(用列表求质数):  9.131449575150953 秒
分解质因数法用时(用生成器求质数):  8.505277230398239 秒

 

posted @ 2016-11-28 21:26  PolarBearInterest  阅读(5378)  评论(0编辑  收藏  举报