Код наибольшего общего делителя в Python [закрыто]

108

Наибольший общий делитель (НОД) чисел a и b - это наибольшее число, которое делит их обоих без остатка.

Один из способов найти НОД двух чисел - это алгоритм Евклида, который основан на наблюдении, что если r- это остаток от деления aна b, то gcd(a, b) = gcd(b, r). В качестве базового случая мы можем использовать gcd(a, 0) = a.

Напишите функцию под названием НОД , который принимает параметры aи bи возвращает их наибольший общий делитель.

Люк Д
источник
попробуйте `np.gcd.reduce ' здесь
ухо

Ответы:

300

Это в стандартной библиотеке .

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

Исходный код inspectмодуля на 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

Начиная с Python 3.5, gcd находится в mathмодуле ; тот, fractionsчто устарел. Более того, inspect.getsourceни один из методов больше не возвращает поясняющий исходный код.

user545424
источник
3
Он не возвращает «номер _largest_ , который делит их обоих без остатка» , например, fractions.gcd(1, -1)есть , -1но 1 > -1то есть 1делит как 1и -1без остатка , и это больше , чем -1, см bugs.python.org/issue22477
JFS
1
@JFSebastian Я не вижу в этом проблемы ... просто посмотрите на комментарий в исходном коде: «Если b == 0, результат будет иметь тот же знак, что и b» , поэтому gcd(1, -1) == -1мне кажется вполне законным.
Марко Бонелли,
@MarcoBonelli: да. Оно ведет себя так, как задокументировано, но это не то определение из учебников, с которым знакомо большинство людей. Прочтите обсуждение, на которое я ссылался выше . Лично мне нравится fractions.gcd()как есть (работает с элементами евклидова кольца).
jfs
1
@JFSebastian FWIW, начиная с Python 3.5, math.gcd(1, -1)возвращается 1.
Acumenus 01
1
@ABB math.gcd () и fractions.gcd () отличаются, как сказано в ответе и комментариях.
jfs
39

Алгоритмы с mn могут работать очень долго.

Этот работает намного лучше:

def gcd(x, y):
    while y != 0:
        (x, y) = (y, x % y)
    return x
нетом
источник
5
Он также есть в стандартной библиотеке.
sayantankhan 07
10
Как вообще работает этот алгоритм? это похоже на магию.
dooderson
20
@netom: нет, так нельзя записать задание ; назначение кортежа используется xдо его назначения. Вы назначены yна x первый , так что теперь yсобирается быть установлен 0(как y % yвсегда 0).
Мартейн Питерс
1
@MartijnPieters да, ты прав, мне следовало использовать временную переменную. вот так: x_ = y; у = х% у; x = x_
netom
3
@netom: который вообще не нужен при использовании назначения кортежа, как это сделано в этом ответе.
Мартейн Питерс
18

Эта версия кода использует алгоритм Евклида для поиска GCD.

def gcd_recursive(a, b):
    if b == 0:
        return a
    else:
        return gcd_recursive(b, a % b)
Анкуш
источник
28
Вы использовали iter в названии, но на самом деле это рекурсивная версия.
Шиплу Мокаддим 01
рекурсия малоэффективна по сравнению с версиями цикла, + вам нужно вызывать ее с помощью b> a
Д-р Гулу
1
def gcd(a, b): if b == 0: return a return gcd(b, a % b)
Андреас К.
16
gcd = lambda m,n: m if not n else gcd(n,m%n)
Йонас Быстрём
источник
3
def gcd(m,n):
    return gcd(abs(m-n), min(m, n)) if (m-n) else n
Дансалмо
источник
5
Никогда не используйте «есть», когда вы хотите сравнить на предмет равенства. Кэш малых целых чисел - это деталь реализации CPython.
Мариус Гедминас
2

Очень краткое решение с использованием рекурсии:

def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a%b)
Preetika Mondal
источник
2

используя рекурсию ,

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

используя while ,

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

используя лямбда,

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

>>> gcd(10,20)
>>> 10
Мохидин бин Мохаммед
источник
1
Лямбда-версия не может работать, потому что у нее нет условий для остановки рекурсии. Я думаю, это просто вызов вашей ранее определенной функции.
rem
1
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)

Другой подход, основанный на алгоритме Евклида.


источник
1
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)
ШАМЫ
источник
1

Я думаю, что другой способ - использовать рекурсию. Вот мой код:

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
источник
Вы не возвращаетесь после рекурсивных вызовов ... попробуйте бежать gcd(10,5)...
Tomerikoo
0

в python с рекурсией:

def gcd(a, b):
    if a%b == 0:
        return b
    return gcd(b, a%b)
Keajer
источник
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
источник
0

Для 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

Для любого a>bили 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
Рао Басварадж
источник
4
своп вары в питоне дети играют: b, a = a, b. попробуйте узнать больше о языке
Джейсон Ху
3
Мне нравится то, что вы говорите, но мне не нравится, как вы это говорите
JackyZhu
0

Мне пришлось сделать что-то подобное для домашнего задания с использованием циклов while. Не самый эффективный способ, но если вы не хотите использовать функцию, это работает:

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])
Ванесса
источник
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))
Сай Пратик
источник
-1

Этот код вычисляет gcd для более чем двух чисел в зависимости от выбора, сделанного # пользователем, здесь пользователь указывает число

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
Прашант
источник
5
Добро пожаловать в Stack Overflow! Не могли бы вы добавить немного повествования, чтобы объяснить, почему этот код работает и что делает его ответом на вопрос? Это будет очень полезно для человека, задающего вопрос, и для всех, кто придет с ним рядом.
Эндрю Барбер
-1

Обмен значениями не сработал для меня. Поэтому я просто создал зеркальную ситуацию для чисел, которые вводятся либо в <b ИЛИ 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)
тройчрой
источник
2
Это даже неверный синтаксис Python. Отступ важен.
Мариус Гедминас
2
А когда а = б? у вас должно быть начальное условие IF, чтобы это уловить.
josh.thomson
-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: ",

great_common_devisor (A)

user4713071
источник
-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
источник
Это самый простой способ ... Не усложняйте!
Par bas
3
Спасибо за предоставленный код, который может помочь решить проблему, но в целом ответы намного полезнее, если они включают объяснение того, для чего предназначен код и почему это решает проблему.
Нейрон
1
Этот код неполный (нет окончательного оператора возврата) и неправильно отформатирован (без отступов). Я даже не уверен, чего breakпытается достичь это заявление.
kdopen
-2

Вот решение, реализующее концепцию 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
Бикрамджит Сингх
источник