Un programme python

Bonjour, je m'appelle Edouard j'ai 14 ans et je suis passionné pas l'informatique. J'ai un problème avec mon programme python, pour faire simple mon programme a pour but de donner le maximum d'informations sur un nombre que l'utilisateur va entrer.
Pour l'instant il dit, si le nombre est pair/impair son nombre de diviseurs, ses diviseurs et si il est premier ou non. Mon problème : je veux créer une liste qui contient les nombres premiers trouvés par l'utilisateur puis demander à l'utilisateur si il veut l'afficher : par exemple si j'entre 5 dans mon programme il va me dire
"-impair -premier -nombre de diviseurs : 2 ses diviseurs sont [1, 5]".
Et si je veux montrer la liste des nombres premiers contenus il me met [5].

Le problème c'est que si je réexécute le programme et que je mets 3 la liste des nombres premiers me sort [3], elle est sensée me sortir [5;3]. le programme n'a pas pris en compte le nombre premier précédent.
Mon but est que le programme prenne en compte le nombre premier précédent et qu'il l'affiche.

Voilà le lien de mon programme, il est sur un éditeur en ligne mais je vous conseille de la copier sur un éditeur plus sophistiqué cela sera plus propre : https://console.basthon.fr/?script=eJy1Vttu2kAQfUfiHyZGVbBCUfBjpOQhUh_aKiBFzROJ0AYv6VbrXbPrRWq_pq_5Dn6sZ33DFAoxbZ0I2XuZOXPmzOyKJNUmI20HlImEdzupESrrB48qCOuP6fv8uZ2MP00e7ouPp0fl_4KQDjw94ioz3JBTpHTybOBAqIWeFR90TV-Mw1jMFzSXnJl-eNXtEOAM7Xeb8aQf5MMeS73FQxIqdQA2ntzd3n-gK6IgxBKJ2enTIUCHnx5JAa-0dIJiLTKaa5VxJQxJXuKnGP9iJSx3xgIUPF4ipkU1_Y4iusbYVUvHVjR8cJtRyoTxVFCZg9mxp8jG1pbcyOEM7cMSC2AI8r3dDpeWtwtmNzSllcf11kgaodSRiOSEWKpQys3dzkIbEhAQGaZeeH80qBi_oFH4hih7tGDeIpOSe0sQw4iYq6zMv2qBRF6M8iw0RSHaiqJShOFekPAjWaE7oVVRVE29ZHDgRbN-fWEYXv-kS2DUxpbjKL9KtBS7uhRLX17EylPQitwc5FwnaQartS1fghK2pqJlHfYIgbFv2mU5foRb12JMx2uR5DlXlifP0g_bakWq_RS3Swcd4wVfexlFcvaz2mcOownmsLgBcReEgyJipmwNfTgchvv76WxfM0EXC6DHAQUW-DfDFnFjQoZUC7rhvPLcV6EHXNMWN2xQX_rmGP1dd2w2xxVrpqNi26JceSI4QGdGu9X6teiMXvvRiT3kt87YJBtGEdl20yz8F12QtqhvDMyqdccPsCaQsi0WW4PCYk4qfiD4AkYLfpuKn28iVMxuqX_nJNqIu2T7fzTpnQaM6fa0VaQBMG2Iq22yNGUmE764UPL3Vduvbh0jkImbxg3RnS6uEVvy_pPo7PBRTaN67xhEgdKklYkKyjK_b-R3jZsbGKPWJxBoi3nCVFy0tXOXCfhnvml6aQtJK-4yWmlxDNvSnWM129RWyVODMv-Kilv6igtGwUmSKCqOkVm_photNS8sn4s5x2gONk_q5OFjQyBbaml-yKjl_aOGEWs19_QVmduQU5QCg2j2tR7v2d9kh1Zynvaj0FdHzUl0Cif7GYl2GBlPxm9hJJh8xtHQpvfUjOS8-917o_zXPeAMqnQ4RviK_8CxmaQSGp37aw5L0gEOJuGvqQb3Bu3yl4jOEFJV9Cdt3wnsFzhyQhI
Merci infiniment pour votre aide

Réponses

  • Bonjour,

    Mets ton programme ici, on n'a pas envie d'aller cliquer ailleurs.

    Cordialement,

    Rescassol
  • Bonjour.

    Je viens de tester, ton programme fait ce que tu dis quand tu rentres un nombre premier.

    Pour garder trace des précédentes occurrences, il est nécessaire de garder en mémoire (pourquoi pas dans un fichier texte), les nombres premiers que le programme trouve, mais en gérant aussi le fait que deux occurrences d'un même nombre premier ne doit pas se traduire par deux affichages de ce nombre.

    Aussi, quand on rentre un nombre non premier, il contient forcément dans sa liste de diviseurs des nombres premiers. Pourquoi ne pas en tenir compte ?

    Par exemple, 35 à entre autres 5 et 7 comme diviseurs premiers.
    Quitte à les calculer, autant les intégrer au fichier à mettre à jour.

    Pour finir, j'ai testé $\sqrt{-1}$, ton programme n'a pas apprécié.
    Dans ce cas, je comprends que tu aies codé en dur l'appartenance à R.

    À bientôt.

    Cherche livres et objets du domaine mathématique :

    Intégraphes, règles log et calculateurs électromécaniques.

  • Voici une petite modif qui permet de garder en mémoire la liste des nombres premiers trouvés mais comme suggéré ci-dessus il vaudrait mieux sauvegarder cette liste dans un fichier si tu en auras besoin par la suite :
    import os, time
    print("\n")
    print("[------BONJOUR------]\n\n\n")                            # entrer un nombre
    info_nombre = True
    terminer = False
    l2 = []
    def clear():
      os.system("clear")
    
    while not terminer:
        nombre = int(input("NOMBRE :  "))
        l = []                                                          # liste qui doit contenir le nombre de diviseurs
        n = 0
        if nombre % 2 == 0:                                             # si le nombre est pair
            print("_________________________________\n\n")
            print("_ pair")                                              # dire "pair"
        else:                                                           # sinon
            print("__________________________________\n\n")
            print("_ impair")                                             # dire "impair"
        for i in range(1, nombre + 1):                                  # faire aller i de 1 au nombre choisi +1
            if nombre % i == 0:                                          # si le reste de la division entre le nombre et i est égale à 0 alors i est un diviseur du nombre
                n = n + 1                                                # compteur
                l = l + [ i]                                              # on ajoute à la liste quid oit contenir le nombre de diviseur l'ensemble des nombre pour lesquels leur reste de la division = 0 entre le nombre et i (autrement di on ajoute le nombre de divisuer dans la liste...)
        print("\n")
        print("_ nombre de diviseurs : ", n, "ses diviseurs sont", l)   # dire le nombre divisuer (n) et la liste des diviseur (l)                                                         # liste qui va contenir les nombres premiers trouvé
        if n == 2:                                                      # si le nombre de divisuer = 2 (le nombre est premier)
            print("\n")
            print("_ premier\n\n")                                      # dire "premier"
            l2 = l2 + [nombre]                                          # on ajoute ce nombre dnas la liste qui doit contenir les nombre premiers
        else:                                                           # sinon
            print("\n")
            print("_ non premier\n\n")                                    # dire "nom premier"
        print("_ appartient à R\n\n")
        print("[1]  --->  Montrer la liste des nombres premiers trouvés.\n"
            "[2]  --->  Ne pas montrer la liste des nombres premiers trouvés\n"
            "[3]  --->  Terminer le programme\n\n")
        q = input(">>>   ")                                             # on demande à l'utilisateur si il veut voir la liste des nombres premiers qu'il a trouvé
        print("")
        print("")
        if q == "1":                                                    # si la réponse est [1] cela veut dire OUI
            print("")
            print("")
            print(l2)                                                     # donc on montre la liste contenant les nombres premiers
            time.sleep(2)
        elif q == "2":                                                  # si la réponse est [2] cela veut dire NON
            print("")
            print("")
            print("OK...\n\n")                                            # dire OK...
            time.sleep(2)
        elif q == "3":
            terminer = True                                            # si la réponse est [2] cela veut dire NON
            print("")
            print("")
            print("OK...\n\n")                                            # dire OK...
            time.sleep(2)
        else:                                                           # sinon
            print("! vous devez remplir ce champ, soit par 1 ou par 2 !") # dire "! vous devez remplir ce champ, soit par 1 ou par 2 !"
            time.sleep(2)
    
  • Merci beaucoup de votre aide ! je vais essayer d'applique ce que vous m'avez conseillez.
  • import os, time
    print("\n")
    print("[------BONJOUR------]\n\n\n")                            # entrer un nombre
    info_nombre = True
    def clear():
      os.system("clear")
    nombre = int(input("NOMBRE :  "))
    l = []                                                          # liste qui doit contenir le nombre de diviseurs
    n = 0
    if nombre % 2 == 0:                                             # si le nombre est pair
       print("_________________________________\n\n")
       print("_ pair")                                              # dire "pair"
    else:                                                           # sinon
      print("__________________________________\n\n")
      print("_ impair")                                             # dire "impair"
    for i in range(1, nombre + 1):                                  # faire aller i de 1 au nombre choisi +1
       if nombre % i == 0:                                          # si le reste de la division entre le nombre et i est égale à 0 alors i est un diviseur du nombre
           n = n + 1                                                # compteur
           l = l + [ i]                                              # on ajoute à la liste quid oit contenir le nombre de diviseur l'ensemble des nombre pour lesquels leur reste de la division = 0 entre le nombre et i (autrement di on ajoute le nombre de divisuer dans la liste...)
    print("\n")
    print("_ nombre de diviseurs : ", n, "ses diviseurs sont", l)   # dire le nombre divisuer (n) et la liste des diviseur (l)
    l2 = []                                                         # liste qui va contenir les nombres premiers trouvé
    if n == 2:                                                      # si le nombre de divisuer = 2 (le nombre est premier)
        print("\n")
        print("_ premier\n\n")                                      # dire "premier"
        l2 = l2 + [nombre]                                          # on ajoute ce nombre dnas la liste qui doit contenir les nombre premiers
    else:                                                           # sinon
      print("\n")
      print("_ non premier\n\n")                                    # dire "nom premier"
    print("_ appartient à R\n\n")
    print("[1]  --->  Montrer la liste des nombres premiers trouvés.\n[2]  --->  Ne pas montrer la liste des nombres premiers trouvés\n\n")
    q = input(">>>   ")                                             # on demande à l'utilisateur si il veut voir la liste des nombres premiers qu'il a trouvé
    print("")
    print("")
    if q == "1":                                                    # si la réponse est [1] cela veut dire OUI
      print("")
      print("")
      print(l2)                                                     # donc on montre la liste contenant les nombres premiers
      time.sleep(2)
    elif q == "2":                                                  # si la réponse est [2] cela veut dire NON
      print("")
      print("")
      print("OK...\n\n")                                            # dire OK...
      time.sleep(2)
    else:                                                           # sinon
      print("! vous devez remplir ce champ, soit par 1 ou par 2 !") # dire "! vous devez remplir ce champ, soit par 1 ou par 2 !"
      time.sleep(2)
    
  • SUPER mille mercis !!! mon programme marche à présent. merci beaucoup !
  • Si tu veux davantage de puissance de calcul, je te conseille de passer au langage C++. J'ai fait une vidéo qui compare avec Python sur un problème gourmand en calculs :
  • Bonsoir,

    Le programme C++ présenté dans la vidéo a tout de même le désavantage de (très probablement) retourner des résultats faux sans crier gare. Il suffit pour cela que l'on sorte du domaine de 'unsigned long long'. Le programme Python n'a pas ce défaut, donc la comparaison est fortement biaisée. Il serait intéressant de voir si Cython offre un gain de performance notable ici.
  • C'est exact, cependant le type unsigned long long int va tout de même jusqu'à 18 446 744 073 709 551 615 donc cela suffit pour une course au temps de vol de 685. Cela avait duré 20 minutes avec Python et 25 secondes avec C++ sur l'ordinateur que j'avais utilisé.

    Pour information, le plafond des 118 736 698 851 769 012 n'est pas dépassé avec un temps de vol inférieur à 1184 que je n'ai pas eu la patience d'atteindre même avec C++. Cependant, le record d'altitude connu est de 2 560 139 341 004 245 682 288 523 934 donc tu as entièrement raison de signaler cette faille.

    En effet, la première fusée Ariane 5, qui utilisait le même calculateur que les fusées Ariane 4, a du être auto-détruite, avec à son bord des satellites scientifiques qui n'ont jamais été remplacés, à cause d'une erreur de dépassement de valeur non gérée.

    Pour calculer en sécurité, comme avec Python, et rapidement, j'opterais plutôt pour l'utilisation d'une classe C++ gérant des entiers sans limite de taille, notamment car je ne connais pas Cython.

    PS : en cas de dépassement non géré en C++, cela génère un simple Warning, c'est plus ou moins critique selon la situation.
  • @philou22 voici un code qui permet de réduire drastiquement le temps de ton algo en Python tout en restant moins rapide que C++. Sur mon PC je fais les 10 millions en 102 secondes.
    def temps_de_vol(n):
        l = 0
        if n&1 == 0:
            d = n & -n
            n = n // d
            l += d.bit_length()-1
    
        while n > 1:
            n = (3*n+1)
            l += 1
    
            d = n & -n
            n = n // d
            l += d.bit_length()-1
    
        return l
    


    PS. merci à Wilfrid pour le n & -n B-)-
  • Si tu veux davantage de puissance de calcul, je te conseille de passer au langage C++. J'ai fait une vidéo qui compare avec Python sur un problème gourmand en calculs

    Le coût d'entrée (et de maintien, car le langage évolue) dans le langage C++ est assez élevé.
    Je conseille vraiment d'utiliser, ou au moins d'essayer Julia.

    Le site web: https://julialang.org/
    Mon livre (lisible en ligne) https://olivier.garet.xyz/livre_julia/
    Voir aussi: https://learnxinyminutes.com/docs/julia/

    Dans mon contexte professionnel, j'ai lâché le couple Scilab/C++ pour tout faire avec Julia.
  • Bonjour
    @philou22 Pour les suites de Syracuse:
    Je pense qu'il y a longtemps que l'on ne s'occupe plus du temps de vol d'un entier i impair ni de son altitude car on peut en construire avec une altitude et un temps de vol supérieur à n'importe quel soit disant record.

    Prends le vol $ i = 2^{1087}-1$ tu verras qu'il va monter en altitude constante pendant 2175 ascensions impaires ou paires constantes avant de tomber sur un multiple de 4 qui se situe à la 1087 ème itération paire. Puis il va redescendre et remonter...etc avant de finir sur le cycle 4,2,1..

    l'altitude à cette itération est de : $6*3^{1087-1} - 2$ = 8,5474 × 10518 :-)

    854739699767433114134028718615064552321307554892985987265722434767449676201396629662007637470279899730562706750774554292465138712421920159892701596297401273323499369926236962708182740286301284663934458399207373463401222889156757494960275243175553464548038535438933062696161054264142017344888616732988423608394218458178787995824246638191131484396687770339157885375649751186502481940212143604293491577220086491075039737173552290923554093045822024771351736408449483876475096196637958270157855371541779081598773775803986772
    et : il peut même aller remonter plus haut ... après ce multiple de 4.
    Je pense que ton record d'altitude....est très loin derrière.
  • Bonjour,

    Comment se fait il que le programme initial ait viré vers la marotte de certains qu'est la conjecture de Syracuse qui n'a rien à voir ?
    Est ce une tentative de rapt de Shtam ?

    Cordialement,

    Rescassol
  • Le fil étant intitulé 'pytohn', il a depuis le départ un petit côté Shtamesque. (:D
  • @raoul.S

    Impressionnant ! En utilisant le programme que tu as donné, par rapport à celui naïf que j'utilisais, la durée de calcul passe de 507 s à 180 s.

    Je me suis renseigné sur les commandes que je ne connaissais pas, comme le & bit à bit ou le reste dans la division euclidienne (il me semble) // et la longueur d'une écriture binaire (signe inclus) bit_length.

    Cependant, je ne comprends pas encore pourquoi l'algorithme est correct, pourrais-tu s'il te plait l'expliquer rapidement ?
  • Ce qu'il faut comprendre c'est qu'en faisant
    n & -n
    
    on récupère la plus grande puissance de deux divisant n : par exemple si n=24 alors n & -n retourne 8 car 24=8*3.

    Par conséquent dans l'algorithme Syracuse au lieu de diviser par deux, éventuellement plusieurs fois avant de retomber sur un nombre impair, on fait toutes les divisions d'un coup jusqu'au prochain nombre impair et on incrémente le temps de vol en conséquence en faisant
    l += d.bit_length()-1
    

    Donc pour résumer le programme :

    - on commence par tester si n est pair en faisant if n&1 == 0, si c'est le cas "on saute" directement au prochain nombre impair par le moyen décrit précédemment. Se placer directement sur un impair nous évite de tester dans la boucle suivante si le nombre est pair ou impair à chaque étape.

    - on se retrouve sur un nombre impair, donc on boucle en sautant les étapes paires à chaque fois toujours comme décrit précédemment.

    Ce qui rend le tout très rapide pour du Python c'est bien le n & -n, pour plus de détails je te renvoie sur le post original de Wilfrid http://www.les-mathematiques.net/phorum/read.php?43,2145186,2208802#msg-2208802
  • Merci pour l'explication @raoul.S
  • Non bien sûr que non je vous ai juste envoyé ce programme car je l'ai testé et il avait l'air de marcher
  • Merci beaucoup ! mais je n'ai aucune base en C++ et je n'ai pas d'éditeur pour ce langage (au passage vous avez gagné 1 abonné) vos vidéos sont très compréhensibles par rapport à d'autres.
Connectez-vous ou Inscrivez-vous pour répondre.