รหัสสำหรับตัวหารร่วมที่ยิ่งใหญ่ที่สุดใน Python [ปิด]


108

ตัวหารร่วมที่ยิ่งใหญ่ที่สุด (GCD) ของ a และ b คือจำนวนที่มากที่สุดที่หารทั้งสองตัวโดยไม่มีเศษเหลือ

วิธีการหนึ่งที่จะหา GCD ของตัวเลขสองเป็นอัลกอริทึมของยุคลิดซึ่งจะขึ้นอยู่กับการสังเกตว่าถ้าrเป็นส่วนที่เหลือเมื่อaถูกหารด้วยแล้วb gcd(a, b) = gcd(b, r)เราสามารถใช้gcd(a, 0) = aไฟล์.

เขียนฟังก์ชั่นที่เรียกว่า GCD ที่ใช้พารามิเตอร์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

ในฐานะที่เป็นของงูใหญ่ 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ดูเหมือนถูกต้องทั้งหมด
Marco Bonelli

@MarcoBonelli: ใช่ มันทำงานตามเอกสาร แต่ไม่ใช่คำจำกัดความของตำราที่คนส่วนใหญ่คุ้นเคย อ่านการสนทนาที่ฉันได้เชื่อมโยงดังกล่าว โดยส่วนตัวแล้วฉันชอบอย่างที่fractions.gcd()เป็นอยู่ (ใช้งานได้กับองค์ประกอบแหวนแบบยุคลิด)
jfs

1
@JFSebastian FWIW เป็นของงูใหญ่ 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: ไม่มีกำหนดไม่สามารถจะเขียนเช่นนั้น; การมอบหมาย tuple ใช้xก่อนที่จะได้รับมอบหมาย คุณกำหนดyให้x ก่อนดังนั้นตอนนี้yจะถูกตั้งค่าเป็น0(เช่นเดียวกับy % y0 เสมอ)
Martijn Pieters

1
@MartijnPieters ใช่คุณพูดถูกฉันควรใช้ตัวแปรชั่วคราว ดังนี้: x_ = y; y = x% y; x = x_
netom

3
@netom: ซึ่งไม่จำเป็นเลยเมื่อใช้การมอบหมาย tuple ตามที่ทำในคำตอบนี้
Martijn Pieters

18

โค้ดเวอร์ชันนี้ใช้อัลกอริทึมของ Euclid ในการค้นหา GCD

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

28
คุณใช้iterในชื่อนี้ แต่จริงๆแล้วมันเป็นเวอร์ชันเรียกซ้ำ
Shiplu Mokaddim

การเรียกซ้ำมีประสิทธิภาพต่ำเมื่อเทียบกับเวอร์ชันลูป + คุณต้องเรียกมันด้วย b> a
Dr. Goulu

1
def gcd(a, b): if b == 0: return a return gcd(b, a % b)
Andreas K.


3
def gcd(m,n):
    return gcd(abs(m-n), min(m, n)) if (m-n) else n

5
อย่าใช้ 'is' เมื่อคุณต้องการเปรียบเทียบเพื่อความเท่าเทียมกัน แคชจำนวนเต็มขนาดเล็กเป็นรายละเอียดการใช้งาน CPython
Marius Gedminas


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
เวอร์ชันแลมบ์ดาไม่สามารถทำงานได้เนื่องจากไม่มีเงื่อนไขที่จะหยุดการเรียกซ้ำ ฉันคิดว่ามันเป็นแค่การเรียกใช้ฟังก์ชันที่คุณกำหนดไว้ก่อนหน้านี้
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

คุณจะไม่กลับมาหลังจากการโทรซ้ำ ... ลองเรียกใช้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
swap vars ใน python คือการเล่นของเด็ก ๆ : b, a = a, b. ลองอ่านเพิ่มเติมเกี่ยวกับภาษา
Jason Hu

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])


-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! คุณจะพิจารณาเพิ่มคำบรรยายเพื่ออธิบายว่าเหตุใดรหัสนี้จึงใช้งานได้และอะไรทำให้เป็นคำตอบสำหรับคำถามนี้ สิ่งนี้จะเป็นประโยชน์มากสำหรับผู้ถามคำถามและคนอื่น ๆ ที่เข้ามา
Andrew Barber

-1

การแลกเปลี่ยนค่าไม่ได้ผลสำหรับฉัน ดังนั้นฉันจึงตั้งค่าสถานการณ์เหมือนมิเรอร์สำหรับตัวเลขที่ป้อนใน a <b OR 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 ที่ถูกต้อง การเยื้องเป็นสิ่งสำคัญ
Marius Gedminas

2
แล้วเมื่อ a = b? คุณควรมีเงื่อนไข 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)


-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

นี่เป็นวิธีที่ง่ายที่สุด ... อย่าทำให้ยาก!
พาร์

3
ขอขอบคุณที่ให้รหัสซึ่งอาจช่วยแก้ปัญหาได้ แต่โดยทั่วไปแล้วคำตอบจะมีประโยชน์มากกว่านี้หากมีคำอธิบายเกี่ยวกับสิ่งที่รหัสตั้งใจจะทำและเหตุใดจึงช่วยแก้ปัญหาได้
Neuron

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.