Bonsoir, je suis nouveau en programmation et j'ai décidé de me lancer dans l'atelier calculatrice. J'ai pour le moment quelques bases en python (conditions, boucles, fonctions) et j'ai décidé de me lancer. Je n'ai bien sur jamais "parser" quelque chose de ma vie.
Le seul problème (bien que le code soit basique et ne marche qu'avec des entiers) c'est qu'il ne respecte pas l'ordre des signes (* avant + par exemple). J'ai beau me casser la tête je vois pas trop comment faire.
J'ai penser a parcourir le tableau au départ et si je trouve * comme signe je fais tab[i-1] * tab[i+1] que j'ajoute dans resultat et ensuite je les suppriment du tableau. Ensuite je reparcourt le tableau avec un résultat déjà présent mais cela ne doit pas être top top. Auriez vous des pistes pour améliorer le code actuel mais aussi arriver à gerer les priorités dans les opérations.
Bonjour, il y a deux trois choses...
Beaucoup de personne aurai utilisé le module des expressions régulières mais j'ai une petite astuce pour toi...
crée une fonction récursive....
string a une méthode split qui crée une liste coupée aux endroit du caractère en argument exemple:
def calc(mystring):
try:
return int(mystring) # est-ce une valeur directe?
except ValueError:
try:
return float(mystring) # est-ce une valeur directe à virgule?
except ValueError:
pass
if "+" in mystring: #application de l'addition
r=0
[r+=calc(i) for i in mystring.split("*")]
return r
#gérer la soustraction... la division...
if "*" in mystring: #application de la multiplication
r=1
[r*=calc(i) for i in mystring.split("*")]
return r
if "^" in mystring:# ... à ton tour de jouer
# puissance... (à composer du moins au plus prio)
Ce code n'a pas été testé: à l'arrache... et à toi de le compléter en ajoutant l'addition avant la multiplication que ça respecte les prio... tu dois même pouvoir gérer les parenthèses...
après python a une méthode "eval" qui pourait parfaitement servir de calculette...
Dans le cas de mon exemple de code: la méthode vas "couper" les string... ça descend dans un arbre qui se compose de la racine aux feuilles puis s'exécute des feuilles à la racine...
Les feuilles dans ce cas c'est les chiffres, la racine c'est l'expression complete...
Dans le sens de composition on divise l'arbre au niveau des faibles priorités (additions) car ce sera exécuté en remontant.
Cas particulier pour les parenthèses, on dit que c'est la priorité ultime mais il faut placer dans le code sa gestion avant l'addition... pour isoler les branches.
Bonne chance, hésite pas à répondre si tu cherche une autre voie ou si tu aboutie avec celle ci (rappel:ce code est non testé et certainement pas exempt de bugs)
Si la violence ne résout pas ton problème c'est que tu n'as pas été assez violent.
Merci pour ta réponse.
Je suis allez voir sur wikipedia et le super cours de Bluestorm à propos de la recursivité et je pense que pour le moment c'est un peu trop haut niveau pour moi comme façon de penser. Ce sera donc mon dernier objectif, reussir la calculette en recursif
Je te remercie pour la petite astuce avec la fonction split que j'ai implémenter et qui allège pas mal le code. Par contre tes exemples ont l'air d'etre d'un niveau assez élevé je vais donc essayer d'alléger le code une fois la gestion des parenthèses mise en place. Désormais la calculette prend en compte l'ordre des opérations avec les '*'. Je vous met le code:
Mon prochain objectif sera les parenthèses, j'ai une petite idée sur comment faire, pensez vous que créer des sous chaine serait bien? Je vous explique, je parcours le tableau depuis la fin, des que je vois une parenthese fermante je prend la suite dans une sous chaine jusqu'a tombé sur une parenthese ouvrante. Si je tombe sur une autre parenthese fermante avant une ouvrante j'ouvre une nouvelle sous chaine et je répète l'opération. Ensuite je traite les sous chaines en remontant de la dernière trouvée à la première puis je traite ce qu'il y avait a l'extérieur des parenthèses.
deuxième remarque, l'opérateur ternaire existe en python depuis le 2.5
a = fstTerm if condition else sndTerm
Après il est plus pythonique de mettre un for à la place du while
for i, e in enumerate(tab):
tab[i-1] = int(tab[i-1])
tab[i+1] = int(tab[i+1])
if e == '+':
resultat = tern(i==1, tab[i-1] + tab[i+1], resultat + tab[i+1])
elif e == '-':
resultat = tern(i==1, tab[i-1] - tab[i+1], resultat - tab[i+1])
elif e == '/':
if tab[i+1] == 0:
resultat = 'impossible'
else:
resultat = tern(i==1, tab[i-1] / tab[i+1], resultat / tab[i+1])
elif e == '^':
resultat = tern(i==1, pow(tab[i-1],tab[i+1]), pow(resultat, tab[i+1]))
else:
resultat = "impossible"
break
Mais je vien de voir une chose ... étonnante... tu concidère qu'il y a nécessairement des espaces entre opérandes et opérateur et que les nombres négatifs ne sont pas en début d'opération...
Ce détail me choque, les éléments pairs ne sont pas nécessairement des opérendes
Ma méthode peut se faire sans récursion...
ma fonction récursive ramenne à peut pret à ça...
Code testé et fonctionnel
def dividelist(l):
div=False
for e in l.split("/"):
e=float(e)
div= div/e if div else e
return div
def multlist(l):
mult=1
for e in l.split("*"):
mult*=dividelist(e)
return mult
def souslist(l):
sous=False
for e in l.split("-"):
e=multlist(e)
sous= sous-e if sous else e
return sous
def addliste(l):
add=0
for e in l.split("+"):
add+=souslist(e)
return add
def calc(mystring):
mystring=mystring.replace(" ","")
return addliste(mystring)
Si la violence ne résout pas ton problème c'est que tu n'as pas été assez violent.
Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.
Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre. En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.
Au lieu de déterrer un sujet il est préférable :
soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
soit de créer un nouveau sujet décrivant votre propre contexte
ne pas répondre à un déterrage et le signaler à la modération
Pas d'aide concernant le code par MP, le forum est là pour ça :)