Inscription / Connexion Nouveau Sujet
Niveau algorithmique
Partager :

Un problème en Python avec des grands entiers

Posté par
LeHibou
03-08-21 à 21:52

Bonjour,

J'utilise ce programme Python pour calculer la somme des chiffres d'un entier :

#somme des chiffres d'un nombre entier
n=eval(input("Entrez un entier positif ou nul : "))
q=n
S=0
while q>0:
     q0=q
     q1=int(q/10)
     r1=q-10*q1
     S=S+r1
     q=q1
     print(q0,q1,r1,S)
print("Somme des chiffres = ",S)

Le principe est évident, à une étape le dernier chiffre est obtenu par n-10*int(n/10), et à l'étape suivante n est remplacé par 10*int(n/10).
Le programme fonctionne bien avec des nombres "raisonnablement" grands, mais il plante par exemple avec 99999999999999999 (17 fois le chiffres 9) pour lequel il sort des résultats négatifs, alors qu'il marche avec 9999999999999999 (16 fois le chiffre 9). Je ne comprends pas pourquoi il plante, puisque Python est censé gérer des entiers arbitrairement longs...
Une idée des experts ?

Posté par
jarod128
re : Un problème en Python avec des grands entiers 04-08-21 à 09:18

Bonjour. Python gère les grands nombres effectivement mais c'est une autre histoire pour les floatant. Je vois donc deux possibilités pour "l'erreur":
La division par 10 ou tout simplement la commande "int" qui force l'utilisation d'entier ("pas long") car le type long est peut-être nommé autrement.
Une possibilité à tester: utilise modulo 10 (%10) pour avoir le dernier chiffre. Ensuite tu le retranches puis tu divises par 10.
Dernière remarque mais c'est peut être hors sujet sur la façon de programmer.
Converti l'entier en chaîne de caractères et parcours cette chaîne.

Posté par
carpediem
re : Un problème en Python avec des grands entiers 04-08-21 à 15:50

salut

en python le "double diviser" ne fait-il pas une division entière tout simplement  :

EX : 23 // 10 renvoie directement 2

Posté par
LeHibou
re : Un problème en Python avec des grands entiers 05-08-21 à 09:15

Merci jarod128 et carpediem pour vos retours.
En combinant vos deux réponses, j'ai pu obtenir un programme qui fonctionne avec des nombres très longs, je vous le livre ci-dessous.
Et pour répondre au commentaire final, de jarod128, effectivement c'aurait été bien plus rapide avec un balayage de la chaîne, mais la méthode était imposée dans un exercice, et je m'y suis tenu

#somme des chiffres d'un nombre
n=eval(input("Entrez un entier positif ou nul : "))
q=n
S=0
while q>0:
     q0=q
     r1=q%10
     q1=(q-r1)//10
     S=S+r1
     q=q1
     print(q0,q1,r1,S)
print("Somme des chiffres = ",S)

Posté par
carpediem
re : Un problème en Python avec des grands entiers 05-08-21 à 10:39

sans utiliser la fonction mod mais uniquement les quatre opérations :

#somme des chiffres d'un nombre
n = eval(input("Entrez un entier positif ou nul : "))
q = n
S = 0
while q > 0 :
     q0 = q // 10
     r = q - 10 * q0
     q = q0
     S = S + r
     print(q0,q1,r1,S)     pourquoi cette ligne d'ailleurs ?
print("Somme des chiffres = ",S)


Posté par
LeHibou
re : Un problème en Python avec des grands entiers 05-08-21 à 10:44

Effectivement, ça marche aussi, merci !

Citation :
print(q0,q1,r1,S)     pourquoi cette ligne d'ailleurs ?

Pour contrôler la progression, elle m'a servi à comprendre de qui ne marchait pas

Posté par
alb12
re : Un problème en Python avec des grands entiers 05-08-21 à 10:47

salut,
version fonctionnelle


def SommeChiffres(n):
    s=0
    while n!=0:
        s=s+n%10
        n=n//10
    return s

Posté par
LeHibou
re : Un problème en Python avec des grands entiers 05-08-21 à 11:31

Citation :
salut,
version fonctionnelle


def SommeChiffres(n):
    s=0
    while n!=0:
        s=s+n%10
        n=n//10
    return s

C'est le sommet de l'élégance, merci !

Posté par
verdurin
re : Un problème en Python avec des grands entiers 08-08-21 à 18:47

Je viens après la bataille mais je trouve l'idée de jarod128 excellente.

n=input("Entrez un entier positif ou nul : ")
s=0
for c in n :
	s+=eval(c)
print("Somme des chiffres = "s)

Posté par
LeHibou
re : Un problème en Python avec des grands entiers 11-08-21 à 09:17

Citation :
Je viens après la bataille mais je trouve l'idée de jarod128 excellente.

n=input("Entrez un entier positif ou nul : ")
s=0
for c in n :
s+=eval(c)
print("Somme des chiffres = "s)

C'est exact, mais comme je l'ai déjà écrit, je crois, le principe de la méthode était une figure imposée de l'exercice

Posté par
ty59847
re : Un problème en Python avec des grands entiers 11-08-21 à 09:46

Je ne pratique pas du tout Python, mais on m'a appris une chose :  en Python, il faut à tout prix éviter les boucles.

Et donc, quelque chose comme ça :

n=input("Entrez un entier positif ou nul : ")
ll = list(n.strip())
print(ll)
l2 = list(map(int,ll))
print(l2)
i = sum(l2)
print(i)


J'ai décomposé... parce que je ne maitrise pas. Mais on doit pouvoir le faire en une seule ligne.

Posté par
LeHibou
re : Un problème en Python avec des grands entiers 11-08-21 à 09:53

Citation :
Je ne pratique pas du tout Python, mais on m'a appris une chose :  en Python, il faut à tout prix éviter les boucles.

Ah bon ? Première nouvelle ! Ça s'appuie sur quelle idée ?
Parce que, éviter les boucles, c'est parfois compliqué

Posté par
ty59847
re : Un problème en Python avec des grands entiers 11-08-21 à 10:25

Python est un langage interprété et non compilé.
Ca veut dire qu'au moment de l'exécution, chaque instruction est traduite en langage machine, puis exécutée.

Et la traduction est plus longue que l'exécution.

Une instruction sum() ...  il y a une seule traduction.

Dans une boucle, à chaque étape, il faut traduire la ligne for i in ...
et il faut traduire la ligne total = total+ eval(c)

En gros, si on traite une chaine de 10 caractères, le traitement par une boucle devrait être 20 fois plus lent que le traitement par l'instruction sum().

Je ne suis pas un pro, et donc j'ai voulu vérifier, pour éviter de dire n'importe quoi.
Et effectivement, c'est assez probant :

import datetime
time0 =  datetime.datetime.now()

for i in range(10):
    ch0 = '123'*1000
    ssum=0
    for c in ch0:
        ssum += eval(c)
time1 =  datetime.datetime.now()

for i in range(10):
    ch0 = '123'*1000
    ll = list(ch0.strip())
    l2 = list(map(int,ll))
    i = sum(l2)
time2 =  datetime.datetime.now()

ch0 = '123'*10000
ll = list(ch0.strip())
l2 = list(map(int,ll))
i = sum(l2)
time3 =  datetime.datetime.now()

print("time0="+ str(time0))
print("time1="+ str(time1))
print("time2="+ str(time2))
print("time3="+ str(time3))  

    
Résultat :

time0=2021-08-11 08:20:46.826159
time1=2021-08-11 08:20:47.692497
time2=2021-08-11 08:20:47.775110
time3=2021-08-11 08:20:47.782303


Pour traiter une chaine de 3000 caractères, et la traiter 10 fois, il faut 8 centièmes de secondes avec la commande sum(), et il faut  pratiquement une seconde avec la boucle et eval()
Et pour traiter une chaine de 30000 caractères (une seule fois)
Il faut seulement un centième de secondes.

Posté par
LeHibou
re : Un problème en Python avec des grands entiers 11-08-21 à 10:31

Citation :
Pour traiter une chaine de 3000 caractères, et la traiter 10 fois, il faut 8 centièmes de secondes avec la commande sum(), et il faut  pratiquement une seconde avec la boucle et eval()
Et pour traiter une chaine de 30000 caractères (une seule fois)
Il faut seulement un centième de secondes.

Ça se tient... Mais cette question de temps est-elle si importante au regard de la complexité induite par l'utilisation de chaînes de caractères pour traiter des nombres ?
Il n'y a pas de bonne ou de moins bonne réponse à cette question, bien sûr, c'est avant tout affaire de choix personnel



Vous devez être membre accéder à ce service...

Pas encore inscrit ?

1 compte par personne, multi-compte interdit !

Ou identifiez-vous :


Rester sur la page

Désolé, votre version d'Internet Explorer est plus que périmée ! Merci de le mettre à jour ou de télécharger Firefox ou Google Chrome pour utiliser le site. Votre ordinateur vous remerciera !