Partage
  • Partager sur Facebook
  • Partager sur Twitter

Un petit exercice: le PGCD

    26 février 2012 à 22:48:40

    Bonjour, je viens proposer un exercice, c'est tout simple mais personnellement j'ai bien aimé le faire c'est assez agréable :)

    Il s'agit tout simplement de demander a l'utilisateur d'entrer 2 nombres, et il doit ressortir soit le PGCD (plus grand diviseur commun) soit que les nombres sont premiers entre eux.


    ma solution (je ne suis pas du tout mais alors pas du tout sur de respecter a la lettre l'éthique de la programmation python, mais ce code marche )

    nombre1 = 0
    nombre2 = 0
    variable1 = 0
    c_est_fini = True  
    pgcd=0
    
    print ('entrez 2 nombre dont vous voulez calculer le PGCD')
    
    nombre1 = input()
    nombre2 = input()
    
    if nombre1<nombre2:
    	variable1=nombre1
    	nombre1=nombre2
    	nombre2=variable1
    
    while c_est_fini: #boucle qui calcule le PGCD tout en verifiant si on modulo pas par 0
    	try:
    		variable1=nombre1%nombre2
    	except ZeroDivisionError:
    		pgcd=nombre1
    		break
    	else:
    		variable1=nombre1%nombre2
    		
    	try:
    		nombre1=nombre2%variable1
    	except ZeroDivisionError:
    		pgcd=nombre2
    		break
    	else:
    		nombre1=nombre2%variable1
    		
    	try:
    		nombre2=variable1%nombre1
    	except ZeroDivisionError:
    		pgcd=variable1
    		break
    	else:
    		nombre2=variable1%nombre1
    		
    if pgcd==1:
    	print ('Les nombres sont premiers entre eux')
    else:
    	print('Le PGCD des deux nombres est', pgcd)
    


    bon code a tous !!
    • Partager sur Facebook
    • Partager sur Twitter
      26 février 2012 à 23:07:55

      Le premier truc qui me soit venu à l'esprit
      def pgcd(a, b):
          return a+b if 0 in (a,b) else pgcd(a % b, b - a % b)
      


      Sinon, ton code n'est pas vraiment pythonnique. Tu te répètes énormément (lignes 18 à 40) et tu peux simplifier des trucs (12 à 15, pas besoin d'une variable intermédiaire).
      • Partager sur Facebook
      • Partager sur Twitter
      Anonyme
        26 février 2012 à 23:11:45

        Juste pour ta culture sache qu'un pgcd peut se déterminer à l'aide du module fractions et de la fonction gcd()

        >>> from fractions import gcd
        >>> gcd(1548722, 152)
        2
        


        Si tu veux tu peux rechercher aussi sur le forum des exemples de fonctions pgcd

        Tu peux aussi rechercher des algorithmes qui t'aideront beaucoup

        >>> def pgcd(a, b):
        ...     while b > 0:
        ...         r = a % b
        ...         a = b
        ...         b = r
        ...     return a
        ... 
        >>> pgcd(1548722, 152)
        2
        


        Si il y a un conseil que je peux te donner c'est de ne pas penser de suite aux exceptions, car en effet

        Citation : Krapow

        je ne suis pas du tout mais alors pas du tout sur de respecter a la lettre l'éthique de la programmation python



        ça n'a pas loupé.
        • Partager sur Facebook
        • Partager sur Twitter
          26 février 2012 à 23:15:50

          Citation : fred1599

          >>> def pgcd(a, b):
          ...     while b > 0:
          ...         r = a % b
          ...         a = b
          ...         b = r
          ...     return a
          ... 
          >>> pgcd(1548722, 152)
          2
          


          Je me permets de mettre l'accent sur ce point encore une fois : avec Python, on peut rendre la boucle beaucoup plus élégante :
          while b > 0:
           a, b = b, a % b
          
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            26 février 2012 à 23:32:53

            Citation

            Je me permets de mettre l'accent sur ce point encore une fois : avec Python, on peut rendre la boucle beaucoup plus élégante



            Ce que tu fais ne rend rien de plus efficace ou de plus pythonic, et peut rendre possible l'incompréhension du PO qui comme tu le vois est débutant.

            • Partager sur Facebook
            • Partager sur Twitter
              26 février 2012 à 23:36:46

              Au contraire, ça montre de façon très claire et évidente ce qui se passe. Une variable inutile est un truc de plus à comprendre, surtout quand on donne des noms très discutables comme a, b ou r... Dans ce cas, l'algorithme est simple et concis, donc le faire en une ligne ou en trois n'a que peu d'importance. Ça gagne en importance quand le code se complexifie.
              Être débutant n'est pas un synonyme d'être stupide, par ailleurs. Je peux comprendre quelqu'un qui ne parle pas de metaclasses à quelqu'un qui a commencé la programmation hier, sauf qu'on ne parle pas ici d'un concept très compliqué.

              Sinon, je ne comprends pas où tu veux en venir avec ta citation. Elle me semble tout simplement hors contexte.
              Message édité...
              • Partager sur Facebook
              • Partager sur Twitter
              Anonyme
                26 février 2012 à 23:45:26

                Citation

                Au contraire, ça montre de façon très claire et évidente ce qui se passe. Une variable inutile est un truc de plus à comprendre, surtout quand on donne des noms très discutables comme a, b ou r... Dans ce cas, l'algorithme est simple et concis, donc le faire en une ligne ou en trois n'a que peu d'importance. Ça gagne en importance quand le code se complexifie.



                Non car elle (la variable r) est dans l'algorithme que je présente en lien, le fait de la retirer peut perturber.

                Citation

                Être débutant n'est pas un synonyme d'être stupide, par ailleurs. Je peux comprendre quelqu'un qui ne parle pas de metaclasses à quelqu'un qui a commencé la programmation hier, sauf qu'on ne parle pas ici d'un concept très compliqué.



                Question de point de vue, soyons honnête, tous les cas existent. Compliqué me semble être un mot très subjectif.
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  26 février 2012 à 23:50:08

                  En plus, si, c'est plus efficace. Dans le sens, plus performant. Python assigne plus rapidement les valeurs aux variables lorsqu'elles sont en une seul instruction (multiple assignment) plutôt que sur plusieurs.

                  <i-need-a-cacahuète >Mais si on veut vraiment être élégant, on indente pas son code avec un seul espace... </i-need-a-cacahuète> :p
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Anonyme
                    27 février 2012 à 0:05:12

                    Citation

                    En plus, si, c'est plus efficace



                    ça reste à prouver ;)

                    Citation

                    Python assigne plus rapidement les valeurs aux variables lorsqu'elles sont en une seul instruction (multiple assignment) plutôt que sur plusieurs.



                    Qui te dis qu'il ne passe pas par les mêmes étapes sans que ça se voit (module dis pour tester?)

                    Je veux bien croire, mais faut démontrer ;) En plus c'est bénéfique pour tout le monde.

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Anonyme
                      27 février 2012 à 0:12:03

                      Je ne retrouve plus les détails, mais déjà ils en parlent ici : http://docs.python.org/tutorial/stdlib [...] e-measurement
                      • Partager sur Facebook
                      • Partager sur Twitter
                        27 février 2012 à 0:14:42

                        Enfin, ce sont des poussières et ce n'est pas vraiment très important. La lisibilité compte pour beaucoup, objectivement je crois que c'est plus facile à lire si on fait l'opération sur une seule ligne que trois.
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Anonyme
                          27 février 2012 à 0:21:56

                          Citation

                          Je ne retrouve plus les détails, mais déjà ils en parlent ici : http://docs.python.org/tutorial/stdlib [...] e-measurement



                          Effectivement, merci pour le lien, même si comme le dis Fayden, se sont pas les assignations qui prennent le plus de temps, c'est toujours bon à savoir.

                          Citation

                          La lisibilité compte pour beaucoup, objectivement je crois que c'est plus facile à lire si on fait l'opération sur une seule ligne que trois



                          Oui si tu ne donnes pas l'algo en face des yeux, tu peux le rendre plus esthétique et plus concis.

                          Mais le principe du code que je donne était de suivre un algorithme tout simplement et de montrer les très peu de différence entre algorithme et code.

                          Par contre comme le PO est débutant, il aurait pu se poser la question de l'absence du r, alors que dans l'algo il s'y trouve.

                          Enfin bref, au niveau optimisation il y a mieux avec les générateurs.

                          • Partager sur Facebook
                          • Partager sur Twitter
                            27 février 2012 à 0:23:29

                            Citation : fred1599

                            Enfin bref, au niveau optimisation il y a mieux avec les générateurs.


                            Ça m'intéresse, qu'est-ce que tu veux dire exactement ?
                            • Partager sur Facebook
                            • Partager sur Twitter
                            Anonyme
                              27 février 2012 à 0:25:58

                              Autant pour moi j'ai confondu avec fibonacci :p
                              • Partager sur Facebook
                              • Partager sur Twitter
                                27 février 2012 à 9:59:41

                                Citation : Fayden

                                Le premier truc qui me soit venu à l'esprit

                                def pgcd(a, b):
                                    return a+b if 0 in (a,b) else pgcd(a % b, b - a % b)
                                



                                Sinon, ton code n'est pas vraiment pythonnique. Tu te répètes énormément (lignes 18 à 40) et tu peux simplifier des trucs (12 à 15, pas besoin d'une variable intermédiaire).




                                Effectivement le code du PO est un code de débutant qui suit pas à pas l'algo d'Euclide et cherche à utiliser des choses complètement inutiles ici.


                                Mais ton code n'est guère pythonnique non plus et est horriblement peu efficace, sans doute moins que celui du PO. D'abord, petit détail, tu effectues deux fois la même division et je te rappelle que la division est l'opération la plus coûteuse des opérations arithmétiques, cela peut aller jusqu'à 20 cycles processeur.
                                Mais surtout, tu utilises une récursion sans mettre en garde, en sorte que ton code s'avère incapable de calculer pgcd(1, 999), je trouve ça vraiment fâcheux.
                                Et les choses ne s'arrangent pas si on dérécursifie ton code, il est affreusement lent et le code du PO s'avère beaucoup plus efficace :


                                def fayden(a, b):
                                    global cpt
                                    while a and b:        
                                        r=a%b
                                        a, b = r, b-r
                                        cpt+=1
                                    return a+b
                                
                                def euclide(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).
                                    """
                                    global cpt
                                    while b:
                                        a, b = b, a%b
                                        cpt+=1
                                    return a
                                
                                def po(nombre1,nombre2):
                                    global cpt
                                    c_est_fini = True
                                    variable1 = 0     
                                    pgcd=0
                                    if nombre1<nombre2:
                                        variable1=nombre1
                                        nombre1=nombre2
                                        nombre2=variable1
                                
                                    while c_est_fini: #boucle qui calcule le PGCD tout en verifiant si on modulo pas par 0
                                
                                        try:
                                            variable1=nombre1%nombre2
                                            cpt+=1
                                        except ZeroDivisionError:
                                            pgcd=nombre1
                                            break
                                        else:
                                            variable1=nombre1%nombre2
                                            cpt+=1
                                            
                                        try:
                                            nombre1=nombre2%variable1
                                            cpt+=1
                                        except ZeroDivisionError:
                                            pgcd=nombre2
                                            break
                                        else:
                                            nombre1=nombre2%variable1
                                            cpt+=1
                                            
                                        try:
                                            nombre2=variable1%nombre1
                                            cpt+=1
                                        except ZeroDivisionError:
                                            pgcd=variable1
                                            break
                                        else:
                                            nombre2=variable1%nombre1
                                            cpt+=1
                                
                                    return pgcd
                                
                                cpt=0
                                
                                
                                for f in (po, fayden, euclide):
                                    print f.__name__
                                    for a,b in [(72*5*49,72*9*169), (2**5*3**8*5**9,2**10*5**12*7**7)]:
                                        cpt=0
                                        print f(a,b), cpt
                                    print
                                



                                po
                                72 10
                                62500000 14
                                
                                fayden
                                72 17
                                62500000 502118
                                
                                euclide
                                72 6
                                62500000 8



                                Citation : fred1599

                                Juste pour ta culture sache qu'un pgcd peut se déterminer à l'aide du module fractions et de la fonction gcd()



                                Bonne remarque.


                                Citation : fred1599


                                Si il y a un conseil que je peux te donner c'est de ne pas penser de suite aux exceptions, car en effet

                                Citation : Krapow

                                je ne suis pas du tout mais alors pas du tout sur de respecter a la lettre l'éthique de la programmation python



                                ça n'a pas loupé.



                                D'accord mais j'ai trouvé que sa tentative était louable pour un débutant.

                                Citation : Fayden

                                Citation : fred1599

                                >>> def pgcd(a, b):
                                ...     while b > 0:
                                ...         r = a % b
                                ...         a = b
                                ...         b = r
                                ...     return a
                                ... 
                                >>> pgcd(1548722, 152)
                                2
                                



                                Je me permets de mettre l'accent sur ce point encore une fois : avec Python, on peut rendre la boucle beaucoup plus élégante



                                Ok mais l'élégance c'est vraiment un luxe quand tu débutes et la compression de code a un coût pour le débutant : il faut qu'il décompresse pour comprendre.


                                Citation : Fayden


                                Être débutant n'est pas un synonyme d'être stupide, par ailleurs. Je peux comprendre quelqu'un qui ne parle pas de metaclasses à quelqu'un qui a commencé la programmation hier, sauf qu'on ne parle pas ici d'un concept très compliqué.



                                Ça c'est ce que tu dis mais j'ai remarqué que tu as une fâcheuse tendance à apprécier la complexité au regard de ta propre perception. Pour enseigner depuis un certain temps déjà la programmation Python à des étudiants novices voire au-delà de débutants, il apparait que demander de calculer le pgcd de deux entiers n'est pas du tout un exercice aisé pour la plupart d'entre eux. D'ailleurs, tu as eu l'occasion toi-même de te tromper lourdement ci-dessus alors que tu n'es plus débutant ...
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  27 février 2012 à 11:38:33

                                  Citation : Fayden

                                  Citation : fred1599

                                  >>> def pgcd(a, b):
                                  ...     while b > 0:
                                  ...         r = a % b
                                  ...         a = b
                                  ...         b = r
                                  ...     return a
                                  ... 
                                  >>> pgcd(1548722, 152)
                                  2
                                  



                                  Je me permets de mettre l'accent sur ce point encore une fois : avec Python, on peut rendre la boucle beaucoup plus élégante :

                                  while b > 0:
                                   a, b = b, a % b
                                  


                                  Je plussoie, les assignations multiples de ce genre sont plus naturelles en Python que le fait de passer par une variable temporaire.

                                  J'entends bien que ce n'est pas nécessairement facile à capter tout de suite pour un débutant, et ça peut éventuellement dérouter la première fois, mais il suffit de passer une fois trois minutes à expliquer que « Lorsque tu fais a, b = b, a, tu inverses le contenu des variables a et b » pour que celui-ci comprenne le principe.

                                  Soulignons au passage que la différence n'est pas que syntaxique : une assignation multiple est une opération atomique (un seul "tic" du programme… intuitivement), là où le passage par une variable temporaire en représente au moins trois.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Zeste de Savoir, le site qui en a dans le citron !
                                    27 février 2012 à 13:06:56

                                    Citation : nohar


                                    Je plussoie, les assignations multiples de ce genre sont plus naturelles en Python que le fait de passer par une variable temporaire.



                                    On peut faire du Python sans devoir être pythonnique. Tu peux très bien vouloir voir le principe de calcul d'un pgcd sans entrer dans les détails du langage (Python ou un autre). Imagine des étudiants qui s'initient à la programmation avec Python et qui ensuite ne feront a priori plus de Python. Leur parler d'affectation par décompression est un truc de plus à apprendre, qui n'est que du sucre syntaxique et qui leur donne juste l'occasion de faire de nouvelles erreurs et qui peuvent être plus ou moins vicieuses et qu'ils devront désapprendre lorsqu'ils feront du C ou du Java.


                                    Citation : nohar


                                    J'entends bien que ce n'est pas nécessairement facile à capter tout de suite pour un débutant, et ça peut éventuellement dérouter la première fois, mais il suffit de passer une fois trois minutes à expliquer que « Lorsque tu fais a, b = b, a,



                                    Ça c'est ce que tu crois parce que tu es doué ;) Mais l'affectation par décompression peut être l'objet de nombreuses incompréhensions. Par exemple, si un zéro écrit a, b = a+ b, a-b, le zéro peut être dans un état d'incompréhension en se demandant lorsque a = a+b, est-ce que le b est celui qui est au départ dans b ou si c'est a-b et, dans ce cas, qu'est-ce que a ? Bref, on peut imaginer un tas de questions que le zéro va se poser et qui l'éloigneront de son calcul de pgcd. L'apparition de ce tytpe d'erreur peut conduire à des surenchères d'apprentissage qui vont finir par te faire donner au zéro le contenu du manuel de référence (je t'invite à examiner le paragraphe 6.2 Assignment statements et tu verras que la chose est en fait assez complexe, en particulier à cause de la possibilité de décompression).


                                    Je ne dis pas qu'il ne faut pas parler de l'affectation par décompression, je dis seulement qu'il n'est absolument pas prouvé que l'ajout de sucre syntaxique facilité l'apprentissage et l'efficacité de réalisation. Je dis aussi qu'il n'y a pas de réponse toute faite comme quoi il faudrait/ ou ne faudrait pas l'enseigner, ça dépend essentiellement du savoir préalable de celui qui apprend, de l'objectif et du contexte d'apprentissage.
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Anonyme
                                      27 février 2012 à 13:16:19

                                      Je pense que le PO recherche surtout à appliquer simplement un algorithme sans trop avoir connaissance de la syntaxe (d'où les try-except dans tous les coins).

                                      Sinon dans le cas contraire, il n'a qu'à utiliser la fonction gcd() du module fractions.

                                      Citation : candide

                                      D'accord mais j'ai trouvé que sa tentative était louable pour un débutant.



                                      Qui a dis le contraire? :)

                                      Seulement si on retire tous les try-except, on se rend compte qu'il fait du C (initialisation de variables inutile), et il serait bon pour lui de bien remarquer que le fonctionnement est très différent.

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        27 février 2012 à 13:24:27

                                        Citation : fred1599

                                        Je pense que le PO recherche surtout à appliquer simplement un algorithme sans trop avoir connaissance de la syntaxe (d'où les try-except dans tous les coins).



                                        Pas sûr justement à cause de ces mêmes try-except. Je pense que le PO a cherché à appliquer ce qu'il a lu dans le tuto et dans une certaine mesure à être pythonnique.



                                        Citation : fred1599


                                        Sinon dans le cas contraire, il n'a qu'à utiliser la fonction gcd() du module fractions.



                                        Ça dépend des objectifs d'apprentissage. En plus, ça suppose qu'il soit au courant d'importer des fonctionnalités de l'extérieur du langage.


                                        Citation : fred1599


                                        Seulement si on retire tous les try-except, on se rend compte qu'il fait du C (initialisation de variables inutile), et il serait bon pour lui de bien remarquer que le fonctionnement est très différent.



                                        Bof. Je pense qu'il s'est surtout embrouillé dans l'algorithme. Est-ce qu'il a déjà fait du C ? à lui de le dire.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          27 février 2012 à 13:43:49

                                          Citation


                                          Leur parler d'affectation par décompression est un truc de plus à apprendre, qui n'est que du sucre syntaxique et qui leur donne juste l'occasion de faire de nouvelles erreurs et qui peuvent être plus ou moins vicieuses et qu'ils devront désapprendre lorsqu'ils feront du C ou du Java.



                                          Ça aussi, je peux l'entendre, même si je suis moyennement d'accord. Disons que la question n'est pas pour moi de savoir s'il faut ou non présenter les choses de cette façon, mais plutôt si le fait de montrer qu'en Python, cet élément de syntaxe permet de coder plus proprement, va nuire ou non à un débutant. Dans l'absolu, je préfère faire la remarque « tiens : dans ce cas là, tu as une façon plus jolie de mettre à jour tes variables », sans pour autant dire que c'est absolument comme cela qu'il faut faire, plutôt que de la passer sous silence.

                                          Évidemment, derrière chaque élément de syntaxe, que ce soit en Python ou dans n'importe quel autre langage bien conçu, il y a une logique et des mécanismes complexes, et il faut être capable de trouver le bon scope à donner aux informations que l'on transmet (étant donné que je suis en train de travailler sur un cours de Python, c'est aussi un truc auquel je suis confronté ces derniers temps…), mais je ne suis pas d'accord avec l'argument « il faudra le désapprendre quand il fera du C ou du Java ».

                                          On ne devrait pas, à mon avis, apprendre un langage de programmation en se contentant des éléments qui sont communs à tous les autres langages. Outre le fait qu'un tel ensemble n'existe pas vraiment, c'est pour moi une erreur que de considérer qu'un élément d'un langage donné serait moins important qu'un autre sous prétexte que l'on ne le trouve pas ou peu dans d'autres langages et qu'il faudrait s'en défaire quand on pratiquera un autre langage à l'avenir.

                                          Quand on apprend à programmer avec un langage, on est forcément amené à un moment ou un autre à devoir « penser en » ce langage et je ne crois pas que ce soit une mauvaise chose. Bien sûr, cela pose problème lorsque l'on apprend de nouveaux langages par la suite, en particulier avec Python, et ce à un niveau bien plus profond que la syntaxe (il n'y a qu'à voir les maladresses de conception que commettent les gens qui se mettent à Python en venant de C++ ou Java…), et il faudra de toute façon désapprendre certaines choses pour en apprendre d'autres de façon à « penser en » ce nouveau langage, mais cette considération ne devrait pas être un frein au moment de l'apprentissage du premier langage. Ce serait absurde.

                                          En gros, je crois qu'il vaut mieux savoir bien programmer en Python, que mal programmer en Python et en Java (même si dans le monde professionnel, on peut observer la tendance inverse).
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          Zeste de Savoir, le site qui en a dans le citron !
                                            27 février 2012 à 13:48:48

                                            Je vous livre ma fonction PGCD ; j'espère que gcd du module fraction est plus rapide, mais sinon, elle devrait être plus rapide que toutes les autres (justes) vues précédemment.

                                            1) on évite, si possible, la récursivité qui est lente (mais jolie, mais lente)
                                            2) on évite, si possible, l'affectation en parallèle (idem)

                                            cela donne le code malin :
                                            def pgcd(a, b):
                                              #if a < 0:  a = -a
                                              #if b < 0:  b = -b
                                            
                                              #if a == 0: return b
                                              #if b == 0: return a
                                            
                                              # lignes à remettre si a ou b peuvent être négatif, ou nuls
                                              while 1:
                                                b %= a
                                                if not b: return a
                                                a %= b
                                                if not a: return b
                                            


                                            Inutile de faire des try, on sait que le diviseur sera non nul !!!

                                            Qui fait le bench sur [1..10000]² ?

                                            =====
                                            Attention, quand je dis que l'affectation parallèle (ou multiple) est lente, ce que je veux dire, c'est que :
                                            a, b = truc(a, b), machin(a, b)

                                            est plus rapide que

                                            prov = truc(a, b)
                                            b = machin(a, b)
                                            a = prov

                                            mais si on peut réfléchir autrement et avoir de manière équivalente
                                            a = bidule(a, b)
                                            b = qqchose(a, b)

                                            alors, c'est le dernier le plus rapide !!!
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              27 février 2012 à 14:57:58

                                              Citation : la Hache

                                              Je vous livre ma fonction PGCD ; j'espère que gcd du module fraction est plus rapide,




                                              La différence semble insignifiante :


                                              # python 2.7
                                              
                                              def lahache(a, b):
                                                while 1:
                                                  b %= a
                                                  if not b: return a
                                                  a %= b
                                                  if not a: return b
                                                  
                                              def euclide(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    
                                              
                                              def alea(m):
                                                  return random.randrange(1,m)
                                              
                                              import time
                                              import random
                                              M=10**10000
                                              N=50
                                              d=10**40
                                              
                                              for f in lahache, euclide:
                                                  print f.__name__
                                                  debut=time.clock()
                                                  for i in range(N):
                                                      f(d*alea(M), d*alea(M))
                                                  fin=time.clock()
                                                  print "TEMPS CPU : %.2f s" %(fin - debut)
                                                  print
                                              


                                              lahache
                                              TEMPS CPU : 10.19 s
                                              
                                              euclide
                                              TEMPS CPU : 10.20 s


                                              J'ai fait d'autres essais (deux éléments consécutifs de la suite de Fibonacci) et les conclusions sont identiques.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                27 février 2012 à 15:20:53

                                                Citation : candide

                                                Mais ton code n'est guère pythonnique non plus et est horriblement peu efficace


                                                Tu aurais pu éviter de perdre ton temps, je le savais déjà. Au cas où tu l'avais oublié, cet exercice, c'est du vu et revu (probablement sur ce forum aussi). J'ai pris 2 minutes pour pondre cette ligne afin de montrer une alternative. Si tu veux, remplace l'appel récursif par pgcd(b, a % b), tu vas enfin pouvoir trouver la réponse à gcd(1, 999) !

                                                Sinon, en temps normal, je ne m'en fais pas trop avec vos benchmarks, mais ne les trouvez-vous pas absolument ridicules dans ce cas-ci ?
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  27 février 2012 à 15:35:08

                                                  Ouh là… pas la peine de s'énerver pour si peu ! :)

                                                  Pour les benches, je pense qu'ils ne sont pas inutiles. En l'occurrence, c'est pas une mauvaise chose que de vérifier qu'un élément de syntaxe est plus rapide à exécuter qu'un autre, surtout dans un langage à aussi haut niveau que Python, où on peut avoir pas mal de magie noire derrière un truc aussi bête que a, b = b, a (naïvement, si je devais l'implémenter j'utiliserais la représentation interne des tuples pour ça, pour utiliser l'unpacking…).

                                                  Après, évidemment, ça revient aussi à couper les cheveux en quatre parce qu'il me semblerait complètement hallucinant d'avoir un facteur 2 entre deux fonctions simplissimes de ce genre, mais au moins, de cette façon, on est fixés.
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                  Zeste de Savoir, le site qui en a dans le citron !
                                                    27 février 2012 à 15:48:35

                                                    Citation : nohar

                                                    Ouh là… pas la peine de s'énerver pour si peu ! :)


                                                    Désolé si c'est l'impression que tu/vous as/avez eue, ce n'était vraiment pas mon intention.

                                                    Citation : nohar

                                                    Pour les benches, je pense qu'ils ne sont pas inutiles. En l'occurrence, c'est pas une mauvaise chose que de vérifier qu'un élément de syntaxe est plus rapide à exécuter qu'un autre, surtout dans un langage à aussi haut niveau que Python, où on peut avoir pas mal de magie noire derrière un truc aussi bête que a, b = b, a [fixed] (naïvement, si je devais l'implémenter j'utiliserais la représentation interne des tuples pour ça, pour utiliser l'unpacking…).


                                                    Je suis d'accord avec toi sur ce point (même si dans ce cas-ci, je ne crois pas que la différence de temps devrait être un facteur pour choisir telle ou telle syntaxe). Dans des cas moins triviaux, ça peut s'avérer pratique. Mais en général, on fait du Python, est-ce que c'est vraiment important ? Ce que je veux dire par là, c'est qu'une fois l'algorithme optimal trouvé (ici, des benchmarks peuvent également s'avérer utiles), les structures de données efficaces utilisées (pareil ici), est-ce que ça vaut vraiment la peine de s'attarder à des détails comme si a, b = b, a est plus rapide que r = a; a = b; b = r ?

                                                    Avant tout, ça me semble être une affaire de syntaxe, où on essaie de privilégier la lisibilité, sans même se soucier des performances.
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      27 février 2012 à 15:51:30

                                                      On est bien d'accord.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                      Zeste de Savoir, le site qui en a dans le citron !
                                                        27 février 2012 à 16:35:39

                                                        Cool pour les bench, ça permet au moins de mettre fin à des légendes urbaines.
                                                        Avec Python 3.2, je confirme les tests de candide (python 2.7), sur plusieurs essais écart minuscule et variable entre lahache, euclide et fractions.gcd.
                                                        Aucune n'ayant l'avantage.

                                                        En revanche, si on devait l'écrire en C, je crois que je mise sur ...

                                                        Au passage, candide ne l'a pas dit, mais le test de pgcd sur deux fibo consécutifs est intéressant, car c'est le pire cas pour deux nombres de taille donnée.
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          27 février 2012 à 16:55:21

                                                          Citation : la Hache


                                                          En revanche, si on devait l'écrire en C, je crois que je mise sur ...



                                                          Voilà, c'est typiquement le genre de trucs auxquels je pense quand je dis qu'on fait souvent des choses bancales en Python quand on connaît déjà bien un(d') autre(s) langage(s). :D

                                                          D'un côté, je suis bien d'accord qu'il ne faut pas perdre de vue ce que ça donnerait en C au-delà d'un certain niveau (mais ici, ce serait pour avoir un niveau très avancé), surtout que l'implémentation standard de Python est en C, ce qui explique somme toute pas mal de choses dans son comportement (donc c'est un peu comme la recommandation de ne pas perdre de vue ce qui se passerait en assembleur quand on fait du C), mais d'un autre, je suis d'autant plus convaincu que quand on se met à Python, il faut se concentrer sur ce qui se passe/se fait/se formule en Python et rien d'autre, comme si les autres langages n'existaient pas/plus.

                                                          J'en retiens surtout que pour écrire un cours de Python complet, (j'entends par là, lisible autant par des débutants complets que des gens qui viennent à Python après avoir déjà codé), il faut non seulement doser la complexité des notions à introduire (ce qui se caractérise surtout par l'ordre dans lequel on les introduit, et le niveau de détail que l'on accorde à chaque passage), mais aussi tous ces points sur lesquels on doit mettre un panneau attention pour éviter aux gens ayant déjà une expérience en programmation de souffrir des stigmates de leur langage précédent.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                          Zeste de Savoir, le site qui en a dans le citron !
                                                            1 mars 2012 à 21:14:37

                                                            Hé ben si j'avais su que je déclencherait une telle vague de polémique...
                                                            Bref, j'ai bien fait, je crois, de préciser que je postais avant tout pour avoir une correction. Ensuite, je savais déjà (bien que je n'avais pas vérifié) qu'il y avait déjà une fonction pgcd, mais je crois que le principe d'un exercice n'est pas de créer tout de suite des choses nouvelles mais d'essayer de reproduire des choses existantes pour pouvoir se corriger (exercice, pour moi, ça veut dire qu'on apprend, on te dis pas d'écrire un livre en anglais pour l'apprendre, on te dis d'en lire et d'essayer de reproduire les tournures de phrases, d'utiliser le vocabulaire dans le bon contexte ... etc) donc bonne remarque, certes, mais qui n'aide pas sachant que je savais déjà que ça existait et que je voulais la refaire pour m'entraîner.
                                                            Et oui, j'ai commencé par apprendre le C (ça doit tellement se voir dans ma façon de déclarer des variables si j'en crois certains messages que vous auriez du vous en douter )
                                                            Je suis d'accord avec nohar quand on apprend un langage il faut se plier a ses règles sinon aucun intérêt de choisir tel ou tel langage, enfin a mon sens.

                                                            Mon utilisation des try/except était en fait dû a ce qu'on evite de diviser par 0 si "variable1" ou "nombre1" valaient 0 avant la fin de la boucle, et je n'ai toujours pas compris comment mon code pouvait tenir en
                                                            while b > 0:
                                                             a, b = b, a % b
                                                            
                                                            ...
                                                            enfin, pour la Hache, il utilise dans son code une boucle infinie, le return casse la boucle?

                                                            Citation : candide

                                                            Pas sûr justement à cause de ces mêmes try-except. Je pense que le PO a cherché à appliquer ce qu'il a lu dans le tuto et dans une certaine mesure à être pythonnique.


                                                            Bien vu, c'est ce que j'ai essayé de faire (en vain apparemment...) mais maintenant je vais pouvoir progresser au moins.

                                                            Ah et aussi, pour la boucle que je dite plus haut, elle est plus rapide sur une ligne que sur 3 si j'ai bien compris, c'est ça? et on ne change la valeur de b qu'une fois par boucle (j'entends on ne la "module" qu'une fois par boucle)?

                                                            en tout cas merci de votre empressement a venir débattre de Python c'est assez intéressant de lire les différents points de vue pour essayer d'adopter le point de vue qui nous semblera au final la meilleure.

                                                            ps; PO = programmeur original? et pas pièce d'or j'imagine...
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            Un petit exercice: le PGCD

                                                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                            • Editeur
                                                            • Markdown