Код найбільшого спільного дільника в Python [закрито]


108

Найбільший спільний дільник (GCD) на a і b - найбільше число, яке ділить їх обох без залишку.

Одним із способів знайти GCD двох чисел є алгоритм Евкліда, який базується на спостереженні, що якщо rзалишок, коли aділиться на b, то gcd(a, b) = gcd(b, r). В якості базового випадку ми можемо використовувати gcd(a, 0) = a.

Напишіть функцію під назвою НСД , який приймає параметри aі bнаступним поверненням їх найбільший спільний дільник.



спробуйте `np.gcd.reduce ' тут
uhoh

Відповіді:


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більше не повертає пояснювальний вихідний код для будь-якого методу.


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

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

10
Як цей алгоритм навіть працює? це як магія.
dooderson

20
@netom: ні, завдання не можна писати так; призначення кортежу використовується xдо його призначення. Ви призначені yна x перший , так що тепер yзбирається бути встановлений 0(як y % yзавжди 0).
Martijn Pieters

1
@MartijnPieters так, ти маєш рацію, я повинен був використовувати тимчасову змінну. ось так: x_ = y; y = x% y; x = x_
netom

3
@netom: який зовсім не потрібен при використанні завдання кортежу, як це зроблено в цій відповіді.
Martijn Pieters

18

Ця версія коду використовує алгоритм Евкліда для пошуку GCD.

def gcd_recursive(a, b):
    if b == 0:
        return a
    else:
        return gcd_recursive(b, a % b)

28
Ви використовували iter в назві, але насправді це рекурсивна версія.
Шиплу Мокаддім

рекурсія є малоефективною порівняно з версіями циклу, + вам потрібно викликати це b> a
д-р Goulu

1
def gcd(a, b): if b == 0: return a return gcd(b, a % b)
Андреас К.


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)

2

використовуючи рекурсію ,

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

використовуючи час ,

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
Версія лямбда не може працювати, оскільки вона не має умови для зупинки рекурсії. Я думаю, що це просто виклик вашої раніше визначеної функції.
рем

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

Ви не повертаєтесь після рекурсивних дзвінків ... спробуйте запустити gcd(10,5)...
Tomerikoo



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
Ласкаво просимо до переповнення стека! Чи можете ви додати трохи розповіді, щоб пояснити, чому цей код працює, і що робить його відповіддю на питання? Це було б дуже корисно для людини, яка задає це питання, і будь-кому іншому, хто йде разом.
Ендрю Барбер

-1

Переміщення значень не спрацювало добре для мене. Тому я просто створив дзеркальну ситуацію для чисел, які вводяться або в <b АБО> 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
Що робити, коли a = b? у вас має бути початкова умова, якщо це зробити.
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: ",

найбільший_коммон_девізор (A)


-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

3
Дякуємо за надання коду, який може допомогти вирішити проблему, але, як правило, відповіді набагато корисніші, якщо вони містять пояснення того, що призначений для цього коду та чому це вирішує проблему.
Нейрон

1
Цей код є неповним (немає остаточного твердження про повернення) та неправильно відформатованим (без відступу). Я навіть не впевнений, чого breakнамагається досягти це твердження.
хтопен

-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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.