web-dev-qa-db-fra.com

Algorithme Euclidien (GCD) à plusieurs nombres?

J'écris donc un programme en Python pour obtenir le GCD de n'importe quel nombre de nombres.

def GCD(numbers):

    if numbers[-1] == 0:
        return numbers[0]


    # i'm stuck here, this is wrong
    for i in range(len(numbers)-1):
        print GCD([numbers[i+1], numbers[i] % numbers[i+1]])


print GCD(30, 40, 36)

La fonction prend une liste de nombres. Cela devrait imprimer 2. Cependant, je ne comprends pas comment utiliser l’algorithme de manière récursive pour qu’il puisse gérer plusieurs nombres. Quelqu'un peut-il expliquer? 

mis à jour, ne fonctionne toujours pas:

def GCD(numbers):

    if numbers[-1] == 0:
        return numbers[0]

    gcd = 0

    for i in range(len(numbers)):
        gcd = GCD([numbers[i+1], numbers[i] % numbers[i+1]])
        gcdtemp = GCD([gcd, numbers[i+2]])
        gcd = gcdtemp

    return gcd

Ok, résolu

def GCD(a, b):

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

et ensuite utiliser réduire, comme

reduce(GCD, (30, 40, 36))
18
Tetramputechture

Puisque GCD est associatif, GCD(a,b,c,d) est identique à GCD(GCD(GCD(a,b),c),d). Dans ce cas, la fonction reduce de Python serait un bon candidat pour réduire les cas pour lesquels len(numbers) > 2 à une simple comparaison à deux nombres. Le code ressemblerait à ceci:

if len(numbers) > 2:
    return reduce(lambda x,y: GCD([x,y]), numbers)

Réduire applique la fonction donnée à chaque élément de la liste, de sorte que quelque chose comme

gcd = reduce(lambda x,y:GCD([x,y]),[a,b,c,d])

est la même chose que faire

gcd = GCD(a,b)
gcd = GCD(gcd,c)
gcd = GCD(gcd,d)

Il ne reste maintenant qu’à coder pour quand len(numbers) <= 2. Passer seulement deux arguments à GCD dans reduce garantit que votre fonction est récurrente au plus une fois (puisque len(numbers) > 2 uniquement dans l'appel d'origine), ce qui présente l'avantage supplémentaire de ne jamais saturer la pile.

27
alexkonradi

Vous pouvez utiliser reduce:

>>> from fractions import gcd
>>> reduce(gcd,(30,40,60))
10

ce qui équivaut à;

>>> lis = (30,40,60,70)
>>> res = gcd(*lis[:2])  #get the gcd of first two numbers
>>> for x in lis[2:]:    #now iterate over the list starting from the 3rd element
...    res = gcd(res,x)

>>> res
10

help on reduce:

>>> reduce?
Type:       builtin_function_or_method
reduce(function, sequence[, initial]) -> value

Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
25

Une solution pour découvrir le LCM de plus de deux nombres dans PYTHON est la suivante:

#finding LCM (Least Common Multiple) of a series of numbers

def GCD(a, b):
    #Gives greatest common divisor using Euclid's Algorithm.
    while b:      
        a, b = b, a % b
    return a

def LCM(a, b):
    #gives lowest common multiple of two numbers
    return a * b // GCD(a, b)

def LCMM(*args):
    #gives LCM of a list of numbers passed as argument 
    return reduce(LCM, args)

Ici, j'ai ajouté +1 dans le dernier argument de la fonction range () car la fonction elle-même commence de zéro (0) à n-1. Cliquez sur l'hyperlien pour en savoir plus sur range () function: 

print ("LCM of numbers (1 to 5) : " + str(LCMM(*range(1, 5+1))))
print ("LCM of numbers (1 to 10) : " + str(LCMM(*range(1, 10+1))))
print (reduce(LCMM,(1,2,3,4,5)))

ceux qui débutent dans python peuvent en savoir plus sur reduction () function par le lien indiqué.

3
sarfarazit08

L'opérateur GCD est commutatif et associatif. Cela signifie que

gcd(a,b,c) = gcd(gcd(a,b),c) = gcd(a,gcd(b,c))

Donc, une fois que vous savez comment le faire pour 2 nombres, vous pouvez le faire pour n’importe quel nombre


Pour le faire pour deux nombres, vous devez simplement implémenter la formule d'Euclid, qui est simplement:

// Ensure a >= b >= 1, flip a and b if necessary
while b > 0
  t = a % b
  a = b
  b = t
end
return a

Définissez cette fonction comme, par exemple, euclid(a,b). Ensuite, vous pouvez définir gcd(nums) comme:

if (len(nums) == 1)
  return nums[1]
else
  return euclid(nums[1], gcd(nums[:2]))

Ceci utilise la propriété associative de gcd () pour calculer la réponse.

3
torquestomp

Ma façon de le résoudre en Python. J'espère que ça aide.

def find_gcd(arr):
    if len(arr) <= 1:
        return arr
    else:
        for i in range(len(arr)-1):
            a = arr[i]
            b = arr[i+1]
            while b:
                a, b = b, a%b
            arr[i+1] = a
        return a
def main(array):
    print(find_gcd(array))

main(array=[8, 18, 22, 24]) # 2
main(array=[8, 24]) # 8
main(array=[5]) # [5]
main(array=[]) # []

Quelques dynamiques comment je le comprends:

ex. [8, 18] -> [18, 8] -> [8, 2] -> [2, 0]

18 = 8x + 2 = (2y) x + 2 = 2z où z = xy + 1

ex. [18, 22] -> [22, 18] -> [18, 4] -> [4, 2] -> [2, 0]

22 = 18w + 4 = (4x + 2) w + 4 = ((2y) x + 2) w + 2 = 2z

0
Zoe L

Essayez d’appeler le GCD() comme suit,

i = 0
temp = numbers[i]
for i in range(len(numbers)-1):
        temp = GCD(numbers[i+1], temp)
0
Deepu