Código para o maior divisor comum em Python [fechado]

108

O maior divisor comum (GCD) de aeb é o maior número que divide os dois sem resto.

Uma maneira de encontrar o GCD de dois números é o algoritmo de Euclides, que se baseia na observação de que se ré o resto quando aé dividido por b, então gcd(a, b) = gcd(b, r). Como caso básico, podemos usar gcd(a, 0) = a.

Escreva uma função chamada gcd que receba parâmetros a e be retorna seu maior divisor comum.

Luke D
fonte

Respostas:

299

Está na biblioteca padrão .

>>> from fractions import gcd
>>> gcd(20,8)
4

Código-fonte do inspectmódulo em Python 2.7:

>>> print inspect.getsource(gcd)
def gcd(a, b):
    """Calculate the Greatest Common Divisor of a and b.

    Unless b==0, the result will have the same sign as b (so that when
    b is divided by it, the result comes out positive).
    """
    while b:
        a, b = b, a%b
    return a

A partir do Python 3.5, gcd está no mathmódulo ; aquele em fractionsestá obsoleto. Além disso, inspect.getsourcenão retorna mais o código-fonte explicativo para nenhum dos métodos.

user545424
fonte
3
Ele não retorna "o _maior_ número que divide os dois sem nenhum resto" , por exemplo, fractions.gcd(1, -1)é , -1mas 1 > -1isto é, 1divide ambos 1e -1sem resto e é maior do que -1, consulte bugs.python.org/issue22477
jfs
1
@JFSebastian Não vejo isso como um problema ... basta olhar para o comentário no código-fonte: "A menos que b == 0, o resultado terá o mesmo sinal de b" , portanto, gcd(1, -1) == -1parece totalmente legítimo para mim.
Marco Bonelli de
@MarcoBonelli: sim. Ele se comporta como documentado, mas não é a definição de livro que a maioria das pessoas está familiarizada. Leia a discussão que vinculei acima . Pessoalmente, gosto do fractions.gcd()jeito que está (funciona em elementos de anel euclidiano).
jfs de
1
@JFSebastian FWIW, a partir do Python 3.5, math.gcd(1, -1)retorna 1.
Acumenus 01 de
1
@ABB math.gcd () e fractions.gcd () são diferentes conforme dito na resposta e nos comentários.
jfs
39

Os algoritmos com mn podem ser muito longos.

Este tem um desempenho muito melhor:

def gcd(x, y):
    while y != 0:
        (x, y) = (y, x % y)
    return x
netom
fonte
5
Este também é o da biblioteca padrão.
sayantankhan,
10
Como esse algoritmo funciona? é como mágica.
dooderson
20
@netom: não, a atribuição não pode ser escrita assim; a atribuição da tupla usa xantes de ser atribuída. Você atribuiu ya x primeira , então agora yvai ser definido para 0(como y % yé sempre 0).
Martijn Pieters
1
@MartijnPieters sim, você está certo, eu deveria ter usado uma variável temporária. assim: x_ = y; y = x% y; x = x_
netom
3
@netom: o que não é necessário ao usar uma atribuição de tupla como feito nesta resposta.
Martijn Pieters
18

Esta versão de código utiliza o Algoritmo de Euclides para encontrar GCD.

def gcd_recursive(a, b):
    if b == 0:
        return a
    else:
        return gcd_recursive(b, a % b)
Ankush
fonte
28
Você usou iter no nome, mas na verdade é uma versão recursiva.
Shiplu Mokaddim
a recursão é pouco eficiente em comparação com as versões de loop, + você precisa chamá-la com b> a
Dr. Goulu
1
def gcd(a, b): if b == 0: return a return gcd(b, a % b)
Andreas K.
15
gcd = lambda m,n: m if not n else gcd(n,m%n)
Jonas Byström
fonte
2
def gcd(m,n):
    return gcd(abs(m-n), min(m, n)) if (m-n) else n
dansalmo
fonte
5
Nunca use 'é' quando você pretende comparar por igualdade. O cache de pequenos inteiros é um detalhe de implementação CPython.
Marius Gedminas
2

Solução muito concisa usando recursão:

def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a%b)
Preetika Mondal
fonte
1

usando recursão ,

def gcd(a,b):
    return a if not b else gcd(b, a%b)

usando enquanto ,

def gcd(a,b):
  while b:
    a,b = b, a%b
  return a

usando lambda,

gcd = lambda a,b : a if not b else gcd(b, a%b)

>>> gcd(10,20)
>>> 10
Mohideen bin Mohammed
fonte
1
A versão lambda não funciona porque não tem condição de parar a recursão. Acho que está apenas chamando sua função definida anteriormente.
rem
0
a=int(raw_input('1st no \n'))
b=int(raw_input('2nd no \n'))

def gcd(m,n):
    z=abs(m-n)
    if (m-n)==0:
        return n
    else:
        return gcd(z,min(m,n))


print gcd(a,b)

Uma abordagem diferente baseada no algoritmo de euclid.


fonte
0
def gcdRecur(a, b):
    '''
    a, b: positive integers

    returns: a positive integer, the greatest common divisor of a & b.
    '''
    # Base case is when b = 0
    if b == 0:
        return a

    # Recursive case
    return gcdRecur(b, a % b)
SHAMS
fonte
0

em python com recursão:

def gcd(a, b):
    if a%b == 0:
        return b
    return gcd(b, a%b)
keajer
fonte
0
def gcd(a,b):
    if b > a:
        return gcd(b,a)
    r = a%b
    if r == 0:
        return b
    return gcd(r,b)
dpeleg2000
fonte
0

Acho que outra maneira é usar a recursão. Aqui está o meu código:

def gcd(a, b):
    if a > b:
        c = a - b
        gcd(b, c)
    elif a < b:
        c = b - a
        gcd(a, c)
    else:
        return a
dexhunter
fonte
Você não está retornando após as chamadas recursivas ... tente executar gcd(10,5)...
Tomerikoo
0

Para a>b:

def gcd(a, b):

    if(a<b):
        a,b=b,a
        
    while(b!=0):
        r,b=b,a%r
        a=r
    return a

Para um a>bou a<b:

def gcd(a, b):

    t = min(a, b)

    # Keep looping until t divides both a & b evenly
    while a % t != 0 or b % t != 0:
        t -= 1

    return t
Rao Baswaraj
fonte
4
troca vars em python é as crianças brincam: b, a = a, b. tente ler mais sobre o idioma
Jason Hu
3
Eu gosto do que você diz, mas não gosto da maneira como você diz
JackyZhu
0

Eu tive que fazer algo assim para uma tarefa de casa usando loops while. Não é a maneira mais eficiente, mas se você não quiser usar uma função, isso funciona:

num1 = 20
num1_list = []
num2 = 40
num2_list = []
x = 1
y = 1
while x <= num1:
    if num1 % x == 0:
        num1_list.append(x)
    x += 1
while y <= num2:
    if num2 % y == 0:
        num2_list.append(y)
    y += 1
xy = list(set(num1_list).intersection(num2_list))
print(xy[-1])
Vanessa
fonte
0
def _grateest_common_devisor_euclid(p, q):
    if q==0 :
        return p
    else:
        reminder = p%q
        return _grateest_common_devisor_euclid(q, reminder)

print(_grateest_common_devisor_euclid(8,3))
Sai Prateek
fonte
-1

Este código calcula o mdc de mais de dois números dependendo da escolha dada pelo # usuário, aqui o usuário fornece o número

numbers = [];
count = input ("HOW MANY NUMBERS YOU WANT TO CALCULATE GCD?\n")
for i in range(0, count):
  number = input("ENTER THE NUMBER : \n")
  numbers.append(number)
numbers_sorted = sorted(numbers)
print  'NUMBERS SORTED IN INCREASING ORDER\n',numbers_sorted
gcd = numbers_sorted[0]

for i in range(1, count):
  divisor = gcd
  dividend = numbers_sorted[i]
  remainder = dividend % divisor
  if remainder == 0 :
  gcd = divisor
  else :
    while not remainder == 0 :
      dividend_one = divisor
      divisor_one = remainder
      remainder = dividend_one % divisor_one
      gcd = divisor_one

print 'GCD OF ' ,count,'NUMBERS IS \n', gcd
Prashant
fonte
5
Bem-vindo ao Stack Overflow! Você consideraria adicionar alguma narrativa para explicar por que esse código funciona e o que o torna uma resposta à pergunta? Isso seria muito útil para a pessoa que fez a pergunta e para qualquer outra pessoa que aparecer.
Andrew Barber
-1

A troca de valor não funcionou bem para mim. Então, acabei de configurar uma situação semelhante a um espelho para os números que são inseridos em a <b OU a> b:

def gcd(a, b):
    if a > b:
        r = a % b
        if r == 0:
            return b
        else:
            return gcd(b, r)
    if a < b:
        r = b % a
        if r == 0:
            return a
        else:
            return gcd(a, r)

print gcd(18, 2)
troychroi
fonte
2
Essa nem mesmo é uma sintaxe válida do Python. O recuo é importante.
Marius Gedminas
2
E quando a = b? você deve ter uma condição IF inicial para detectar isso.
josh.thomson
-1

Esta é a solução que implementa o conceito de Iteration:

def gcdIter(a, b):
    '''
    a, b: positive integers

    returns: a positive integer, the greatest common divisor of a & b.
    '''
    if a > b:
        result = b
    result = a

    if result == 1:
        return 1

    while result > 0:
        if a % result == 0 and b % result == 0:
            return result
        result -= 1
Bikramjeet Singh
fonte
-2
#This program will find the hcf of a given list of numbers.

A = [65, 20, 100, 85, 125]     #creates and initializes the list of numbers

def greatest_common_divisor(_A):
  iterator = 1
  factor = 1
  a_length = len(_A)
  smallest = 99999

#get the smallest number
for number in _A: #iterate through array
  if number < smallest: #if current not the smallest number
    smallest = number #set to highest

while iterator <= smallest: #iterate from 1 ... smallest number
for index in range(0, a_length): #loop through array
  if _A[index] % iterator != 0: #if the element is not equally divisible by 0
    break #stop and go to next element
  if index == (a_length - 1): #if we reach the last element of array
    factor = iterator #it means that all of them are divisibe by 0
iterator += 1 #let's increment to check if array divisible by next iterator
#print the factor
print factor

print "The highest common factor of: ",
for element in A:
  print element,
print " is: ",

maior_common_devisor (A)

user4713071
fonte
-2
def gcdIter(a, b):
gcd= min (a,b)
for i in range(0,min(a,b)):
    if (a%gcd==0 and b%gcd==0):
        return gcd
        break
    gcd-=1
Par bas
fonte
Esta é a maneira mais fácil ... Não torne isso difícil!
Par bas de
3
Obrigado por fornecer um código que pode ajudar a resolver o problema, mas geralmente as respostas são muito mais úteis se incluírem uma explicação do que o código se destina a fazer e por que isso resolve o problema.
Neurônio
1
Este código está incompleto (sem declaração final de retorno) e formatado incorretamente (sem indentação). Eu nem tenho certeza do que essa breakdeclaração está tentando alcançar.
kdopen