A voir également:
- Calculer le carré d'un nombre en javascript
- Comment calculer la moyenne sur excel - Guide
- Metre carré clavier ✓ - Forum Bureautique
- Nombre de jours entre deux dates excel - Guide
- Quel est le raccourci clavier pour m2 et m3 ? ✓ - Forum Bureautique
- Signe au carré - Forum iPad
8 réponses
Bonsoir,
Tu n'as pas une erreur quand tu as un '²' en dernière position?
En effet, tu passes par document.getElementById('zoneCalcul').value.slice(i+1, i+1) == '²' et tu fais un slice sur une valeur qui n'existe pas.
De plus, si tu as plus d'un '²' dans ta chaine, ça ne va pas fonctionner car tu vas avoir un truc du genre:
2²+13²
Et donc quand tu vas faire un eval, tu n'auras pas la bonne solution.
Sinon ce que dit dOoOb n'est pas la bonne solution (en tout cas je le pense), car dans ce cas tu as un problème avec les opérateurs ² successifs (que toi tu pourrais gérer plus facilement gérer en améliorant le code que tu as, si j'étais toi j'insèrerais une parenthèse fermante dès que je rencontres un ², et une parenthèse ouvrante dès que je rencontre un opérateur arithmétique).
Exemple:
3²², ton programme actuel devrait te retourner 81
Si tu implémentes la solution de dOoOb, ça va transformer ton expression en 3*3², et tu ne vas pas pouvoir enchainer la fin de cette manière (si tu continue tu vas avoir 3*3*3 donc pas la bonne solution). Il te faudrait alors insérer des parenthèses, et donc reparcourir toute ta chaine dans le sens inverse pour en insérer.
Après tu peux bien sûr considérer qu'il n'est pas valide d'avoir des opérateurs ² successifs, ce qui peut être tout à fait envisageable.
@dOoOb
Ce que EmoTik fait dans sa fonction est exactement ce que tu veux faire sauf qu'il parcourt sa chaîne en partant de la fin.
Ca lui évite donc notamment de stocker inutilement des valeurs inutiles (car il ne stocke que les chaines qui sont suivies par un '²'). C'est quand même mieux de parcourir la chaine en partant de la fin.
Voilà, je pense que la méthode la plus simple est claire est dans ta fonction calculer :
- tu parcours ta chaine depuis la fin comme tu fais
- dès que tu trouves le caractère '²', tu appelles une fonction qui t'extrait la sous-chaine qui est passée à l'opérateur ², (tu appelles récursivement calculer() de manière à gérer les ² successifs si tu veux, en améliorant calculer() pour qu'elle te retourne une valeur, et non pas pour qu'elle affiche elle-même le résultat. Tu pourras l'appeler depuis une méthode affiche qui fera appel à calculer, et qui affichera le résultat obtenu) et qui te retourne la chaine opérande*opérande
- tu t'arranges pour modifier ta chaine pour supprimer le caractère '²' ainsi que son opérande, et pour insérer et non pas concaténer la chaine (opérande*opérande) retournée
Bon courage :)
Tu n'as pas une erreur quand tu as un '²' en dernière position?
En effet, tu passes par document.getElementById('zoneCalcul').value.slice(i+1, i+1) == '²' et tu fais un slice sur une valeur qui n'existe pas.
De plus, si tu as plus d'un '²' dans ta chaine, ça ne va pas fonctionner car tu vas avoir un truc du genre:
2²+13²
premier ²: valfin = 13*13 deuxième ²: valfin=2*213*13
Et donc quand tu vas faire un eval, tu n'auras pas la bonne solution.
Sinon ce que dit dOoOb n'est pas la bonne solution (en tout cas je le pense), car dans ce cas tu as un problème avec les opérateurs ² successifs (que toi tu pourrais gérer plus facilement gérer en améliorant le code que tu as, si j'étais toi j'insèrerais une parenthèse fermante dès que je rencontres un ², et une parenthèse ouvrante dès que je rencontre un opérateur arithmétique).
Exemple:
3²², ton programme actuel devrait te retourner 81
Si tu implémentes la solution de dOoOb, ça va transformer ton expression en 3*3², et tu ne vas pas pouvoir enchainer la fin de cette manière (si tu continue tu vas avoir 3*3*3 donc pas la bonne solution). Il te faudrait alors insérer des parenthèses, et donc reparcourir toute ta chaine dans le sens inverse pour en insérer.
Après tu peux bien sûr considérer qu'il n'est pas valide d'avoir des opérateurs ² successifs, ce qui peut être tout à fait envisageable.
@dOoOb
Ce que EmoTik fait dans sa fonction est exactement ce que tu veux faire sauf qu'il parcourt sa chaîne en partant de la fin.
Ca lui évite donc notamment de stocker inutilement des valeurs inutiles (car il ne stocke que les chaines qui sont suivies par un '²'). C'est quand même mieux de parcourir la chaine en partant de la fin.
Voilà, je pense que la méthode la plus simple est claire est dans ta fonction calculer :
- tu parcours ta chaine depuis la fin comme tu fais
- dès que tu trouves le caractère '²', tu appelles une fonction qui t'extrait la sous-chaine qui est passée à l'opérateur ², (tu appelles récursivement calculer() de manière à gérer les ² successifs si tu veux, en améliorant calculer() pour qu'elle te retourne une valeur, et non pas pour qu'elle affiche elle-même le résultat. Tu pourras l'appeler depuis une méthode affiche qui fera appel à calculer, et qui affichera le résultat obtenu) et qui te retourne la chaine opérande*opérande
- tu t'arranges pour modifier ta chaine pour supprimer le caractère '²' ainsi que son opérande, et pour insérer et non pas concaténer la chaine (opérande*opérande) retournée
Bon courage :)
Alors tout d'abord, je tiens à vous remercier pour vos réponses rapides et enrichissantes et à m'excuser du temps de réponse de ma part mais j'étais en plein partiels de fin d'année; voilà pour la petite histoire !
J'ai pas très très bien saisi l'autre concept que celui des parenthèses Marco. J'ai saisi comment placer des parenthèses, il n'y a rien de plus simple et c'est vrai que de pouvoir gérer cela est un plus. Mais est-ce que le eval gère les parenthèses ?
J'ai fais la trace de mon algo des dixaines de fois je ne comprends pas ou la base bug ? Je comprend pour le slice de fin mais pas le reste ! ça devrait fonctionner non ?
J'ai essayer de modifier un peu le code mais rien n'y fait, je vais me repencher dessus !
Mais pourrais-tu m'expliquer un peu plus en détail la méthode que tu propose car je la trouve très ressemblante à la mienne mais je ne vois pas exactement ce qui change!
Merci encore.
J'ai pas très très bien saisi l'autre concept que celui des parenthèses Marco. J'ai saisi comment placer des parenthèses, il n'y a rien de plus simple et c'est vrai que de pouvoir gérer cela est un plus. Mais est-ce que le eval gère les parenthèses ?
J'ai fais la trace de mon algo des dixaines de fois je ne comprends pas ou la base bug ? Je comprend pour le slice de fin mais pas le reste ! ça devrait fonctionner non ?
J'ai essayer de modifier un peu le code mais rien n'y fait, je vais me repencher dessus !
Mais pourrais-tu m'expliquer un peu plus en détail la méthode que tu propose car je la trouve très ressemblante à la mienne mais je ne vois pas exactement ce qui change!
Merci encore.
Salut EmoTik !
Mais est-ce que le eval gère les parenthèses ? Oui, heureusement sinon eval() serait vraiment une fonction pourrie :)
Tu as compris que le '²' en dernière position devait planter ta fonction, donc je considère que tu as corrigé le problème.
En ce qui concerne le :
premier ²: valfin = 13*13
deuxième ²: valfin=2*213*13
que j'ai dit la dernière fois, en fait je me suis trompé (mea culpa...), la variable nombre est bien castée en int avant la multiplication donc ça fonctionne, n'y tiens pas compte.
Maintenant on va dérouler ton programme si tu as 2²-13² comme expression, et voir comment il se comporte pour trouver les bugs :
Conclusion : corrige déjà les deux bugs soulignés ci-dessus. Une fois que ce sera fait essaie de trouver une méthode pour utiliser tes opérateurs convenablement (valFin=nombre+valFin ne marche qu'avec l'opérateur plus pour le moment).
Cordialement
Mais est-ce que le eval gère les parenthèses ? Oui, heureusement sinon eval() serait vraiment une fonction pourrie :)
Tu as compris que le '²' en dernière position devait planter ta fonction, donc je considère que tu as corrigé le problème.
En ce qui concerne le :
premier ²: valfin = 13*13
deuxième ²: valfin=2*213*13
que j'ai dit la dernière fois, en fait je me suis trompé (mea culpa...), la variable nombre est bien castée en int avant la multiplication donc ça fonctionne, n'y tiens pas compte.
Maintenant on va dérouler ton programme si tu as 2²-13² comme expression, et voir comment il se comporte pour trouver les bugs :
2²-13² valFin = ""; x = 6 i=6; On rentre dans le premier else, puis dans le while : i=5 Deuxième tour de boucle : on passe dans le else puis dans le if cette fois: z=5 nombre="" nombre=3 z=4 nombre=13 z=3 nombre=13*13=169 valfin=169 i=3 Ok, on continue avec un nouveau tour de boucle : on entre dans le else puis else : valfin = - +valFin Ici tu as un problème déjà, car ton opérateur n'est pas géré i=2 Nouveau tour de boucle : on passe direct dans le if : i=1 C'est presque fini : nouveau tour de boucle : on passe dans le else puis le if : z=1 nombre="" nombre=2 z=0 Ici tu as un nouveau problème car ton while ne spécifie pas que z peut valoir 0 : tu as une boucle infinie à moins que la fonction slice(0,0) ne plante nombre=2*2=4 valFin=4+valFin=4+169=173 i=0 Résultat : 173 (résultat attendu : -165)
Conclusion : corrige déjà les deux bugs soulignés ci-dessus. Une fois que ce sera fait essaie de trouver une méthode pour utiliser tes opérateurs convenablement (valFin=nombre+valFin ne marche qu'avec l'opérateur plus pour le moment).
Cordialement
Merci !
Pour le ² qui se trouve à la fin il suffit que je mette la valeur de i = x , non ?
Pas besoin d'un if de plus !?
Et pour ce qui est de la transmission de l'opérateur j'ai bien cherché mais je ne trouve rien du tout ! Je n'y arrive pas ! J'ai passé plusieurs sites en revues, quelques test de codes mais rien ne passe !
J'ai réglé la boucle infini en ajoutant while(..... && z>=0)...
Car il me semble que slice parte de (0,0) et non pas de (1,1) si ?
Encore merci .
Pour le ² qui se trouve à la fin il suffit que je mette la valeur de i = x , non ?
Pas besoin d'un if de plus !?
Et pour ce qui est de la transmission de l'opérateur j'ai bien cherché mais je ne trouve rien du tout ! Je n'y arrive pas ! J'ai passé plusieurs sites en revues, quelques test de codes mais rien ne passe !
J'ai réglé la boucle infini en ajoutant while(..... && z>=0)...
Car il me semble que slice parte de (0,0) et non pas de (1,1) si ?
Encore merci .
Yo !
Pour le ² qui se trouve à la fin il suffit que je mette la valeur de i = x , non ?
Pas besoin d'un if de plus !?
En fait tu n'as pas besoin du code suivant :
Il faut que tu commences à effectuer ton traitement dès que tu détectes le '²' (donc pas de bidouille avec i+1, donc pas de dépassement de bornes).
J'ai réglé la boucle infini en ajoutant while(..... && z>=0)...
Car il me semble que slice parte de (0,0) et non pas de (1,1) si ?
Pour le while, c'est ok. Effectivement, le slice part de 0. D'ailleurs, tu dois avoir une petite erreur dans l'initialisation de x (et donc de i) :
Et pour ce qui est de la transmission de l'opérateur j'ai bien cherché mais je ne trouve rien du tout ! Je n'y arrive pas ! J'ai passé plusieurs sites en revues, quelques test de codes mais rien ne passe !
Pour ça en fait il faut utiliser la magie de javascript (je n'ai jamais fait de javascript, ni jamais lu aucun cours/tuto donc je n'y connais pratiquement rien, mais je sais que les variables ne sont pas typées, et donc que tu peux aisément jouer avec les cast).
Pour te mettre sur la bonne voie, voici un exemple :
Exécuté, ce code retourne 6 (alors que chaine, op et chaine2 sont des strings, donc la concaténation des 3 en est une aussi).
C'est pour te montrer que tu dois utiliser les chaines! Si tu tombes sur un opérateur, tu récupères la chaine représentant cet opérateur ('+', '-', '/', '*', ...), tu la concatènes à valFin par le début (valFin = op + valFin) et tu poursuis ton traitement.
valFin est de type string, il ne faut pas l'oublier. Quand tu arriveras à la fin de ton traitement et que tu exécuteras eval(valFin), la fonction eval va automatiquement caster valFin et ça va marcher :)
Pour le ² qui se trouve à la fin il suffit que je mette la valeur de i = x , non ?
Pas besoin d'un if de plus !?
En fait tu n'as pas besoin du code suivant :
if (document.getElementById('zoneCalcul').value.slice(i+1, i+1) == '²') ...
Il faut que tu commences à effectuer ton traitement dès que tu détectes le '²' (donc pas de bidouille avec i+1, donc pas de dépassement de bornes).
J'ai réglé la boucle infini en ajoutant while(..... && z>=0)...
Car il me semble que slice parte de (0,0) et non pas de (1,1) si ?
Pour le while, c'est ok. Effectivement, le slice part de 0. D'ailleurs, tu dois avoir une petite erreur dans l'initialisation de x (et donc de i) :
x = document.getElementById('zoneCalcul').value.length;doit être remplacé par
x = document.getElementById('zoneCalcul').value.length - 1;pour coller aux bornes.
Et pour ce qui est de la transmission de l'opérateur j'ai bien cherché mais je ne trouve rien du tout ! Je n'y arrive pas ! J'ai passé plusieurs sites en revues, quelques test de codes mais rien ne passe !
Pour ça en fait il faut utiliser la magie de javascript (je n'ai jamais fait de javascript, ni jamais lu aucun cours/tuto donc je n'y connais pratiquement rien, mais je sais que les variables ne sont pas typées, et donc que tu peux aisément jouer avec les cast).
Pour te mettre sur la bonne voie, voici un exemple :
var chaine="2"; var op = "+"; var chaine2="4"; alert(eval(chaine+op+chaine2));
Exécuté, ce code retourne 6 (alors que chaine, op et chaine2 sont des strings, donc la concaténation des 3 en est une aussi).
C'est pour te montrer que tu dois utiliser les chaines! Si tu tombes sur un opérateur, tu récupères la chaine représentant cet opérateur ('+', '-', '/', '*', ...), tu la concatènes à valFin par le début (valFin = op + valFin) et tu poursuis ton traitement.
valFin est de type string, il ne faut pas l'oublier. Quand tu arriveras à la fin de ton traitement et que tu exécuteras eval(valFin), la fonction eval va automatiquement caster valFin et ça va marcher :)
Bonsoir,
J'ai bien fais tout ce que tu m'avais dit de faire marco !
J'ai tout d'abord supprimé le if innutile.
Au tout début (après déclaration des variables), j'ai ajouté ceci :
if(document.getElementById('zoneCalcul').value.length > 0)
{
....tout le code .....
}
else
{
document.getElementById('zoneCalcul').value = "Entrer des valeurs...";
}
Comme ça, cela nous permet de voir si des valeurs ont été entrées !
Ensuite j'initialise x : x = document.getElementById('zoneCalcul').value.length - 1;
Je mets i et valFin :
valFin = "";
i=(x);
Ensuite je regarde si x vaut 0 :
if(x == 0)
{
valFin = document.getElementById('zoneCalcul').value;
}
dans le cas présent, pas de else, on va à la fin et on renvoi rien ou le seul nombre qui existe !!
Enfin dans le esle :
while(i >= 0)
{
if(document.getElementsById('zoneCalcul').value.slice(i, i) == "²")
{
i--;
z = i;
nombre = "";
while(document.getElementById('zoneCalcul').value.slice(z, z) != "+" && document.getElementById('zoneCalcul').value.slice(z, z) != "-" && document.getElementById('zoneCalcul').value.slice(z, z) != "*" && document.getElementById('zoneCalcul').value.slice(z, z) != "/" && z>= 0)
{
nombre = document.getElementById('zoneCalcul').value.slice(z, z) + nombre;
z--;
}
nombre = nombre * nombre;
valfin = nombre + valfin;
i = z;
}
else
{
oper="";//On mets la chaine vide!
if(document.getElementById('zoneCalcul').value.slice(i, i) == "+")
oper = "+";
if(document.getElementById('zoneCalcul').value.slice(i, i) == "-")
oper = "-";
if(document.getElementById('zoneCalcul').value.slice(i, i) == "*")
oper = "*";
if(document.getElementById('zoneCalcul').value.slice(i, i) == "/")
oper = "/";
if(oper.length >0)
{
valFin = oper + valFin;
i--;
}
else
{
valFin = document.getElementById('zoneCalcul').value.slice(i, i) + valFin;
i--;
}
}
}
Comme tu peux le constater j'utilise une variable ("String") afin de bien concaténer la chaine dans mon calcul ! Mais ça pose problème toujours pas de résultat !
Si tu veux des explications du code j'en donnerais plus !
Merci encore !
J'ai bien fais tout ce que tu m'avais dit de faire marco !
J'ai tout d'abord supprimé le if innutile.
Au tout début (après déclaration des variables), j'ai ajouté ceci :
if(document.getElementById('zoneCalcul').value.length > 0)
{
....tout le code .....
}
else
{
document.getElementById('zoneCalcul').value = "Entrer des valeurs...";
}
Comme ça, cela nous permet de voir si des valeurs ont été entrées !
Ensuite j'initialise x : x = document.getElementById('zoneCalcul').value.length - 1;
Je mets i et valFin :
valFin = "";
i=(x);
Ensuite je regarde si x vaut 0 :
if(x == 0)
{
valFin = document.getElementById('zoneCalcul').value;
}
dans le cas présent, pas de else, on va à la fin et on renvoi rien ou le seul nombre qui existe !!
Enfin dans le esle :
while(i >= 0)
{
if(document.getElementsById('zoneCalcul').value.slice(i, i) == "²")
{
i--;
z = i;
nombre = "";
while(document.getElementById('zoneCalcul').value.slice(z, z) != "+" && document.getElementById('zoneCalcul').value.slice(z, z) != "-" && document.getElementById('zoneCalcul').value.slice(z, z) != "*" && document.getElementById('zoneCalcul').value.slice(z, z) != "/" && z>= 0)
{
nombre = document.getElementById('zoneCalcul').value.slice(z, z) + nombre;
z--;
}
nombre = nombre * nombre;
valfin = nombre + valfin;
i = z;
}
else
{
oper="";//On mets la chaine vide!
if(document.getElementById('zoneCalcul').value.slice(i, i) == "+")
oper = "+";
if(document.getElementById('zoneCalcul').value.slice(i, i) == "-")
oper = "-";
if(document.getElementById('zoneCalcul').value.slice(i, i) == "*")
oper = "*";
if(document.getElementById('zoneCalcul').value.slice(i, i) == "/")
oper = "/";
if(oper.length >0)
{
valFin = oper + valFin;
i--;
}
else
{
valFin = document.getElementById('zoneCalcul').value.slice(i, i) + valFin;
i--;
}
}
}
Comme tu peux le constater j'utilise une variable ("String") afin de bien concaténer la chaine dans mon calcul ! Mais ça pose problème toujours pas de résultat !
Si tu veux des explications du code j'en donnerais plus !
Merci encore !
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Oui, de toute façons je n'arrive pas du tout à avancer sur ce projet !
Je te remercie pour toute l'aide que tu m'apportes. Si tu as besoin du fichier original, je peux te l'envoyer !
Bonne soirée. Merci
Je te remercie pour toute l'aide que tu m'apportes. Si tu as besoin du fichier original, je peux te l'envoyer !
Bonne soirée. Merci
Ta fonction calculer m'a l'air trèèèèèèèès compliquée. Je te propose plus claire :
tu parcours ton expression (mettons 3*5+2²), dès que tu tombes sur un opérateur tu commences à enregistrer le bout de chaine qui vient ensuite jusqu'au prochain opérateur ou carré (ici on aura * donc tu sauves 5, mais 5 n'est pas suivit d'un carré, donc on continue ; puis 2 et il est suivit d'un carré, donc on récupère 2 et on remplace le carré par "*2" pour simuler le carré) et ainsi de suite jusqu'à la fin...
tu parcours ton expression (mettons 3*5+2²), dès que tu tombes sur un opérateur tu commences à enregistrer le bout de chaine qui vient ensuite jusqu'au prochain opérateur ou carré (ici on aura * donc tu sauves 5, mais 5 n'est pas suivit d'un carré, donc on continue ; puis 2 et il est suivit d'un carré, donc on récupère 2 et on remplace le carré par "*2" pour simuler le carré) et ainsi de suite jusqu'à la fin...
Le but n'est certes pas de faire un truc poussé de toutes façons, sinon on ne le fait pas en javascript, et on commence par écrire son propre compilateur pour pouvoir gérer les priorités de manière propre, comme tu as du le voir à l'école je n'en doute pas.
Ne pas faire un truc poussé ne signifie pas coder comme un porc, les algorithmes ce n'est pas fait pour les chiens (le monsieur en iut d'info n'aurait pas de cours dans ce domaine sinon), et même pour un programme simple, c'est important de penser aux détails (tes profs d'infos ne t'ont jamais dit "le diable se cache dans les détails" ?), et donc aux optimisations.
Enfin, je n'ai pas dit que ta méthode était nulle, donc ne le prends pas mal, j'ai simplement donné mon avis en disant qu'elle n'était pas optimale et en présentant mes arguments. Tu es tout à fait libre d'en faire autant avec ma solution, qui n'est pas optimale elle non plus, je n'en doute pas.
Ta méthode retournera le résultat escompté, personne ne le dément, elle est simplement d'un point de vue algorithmique moins bien pensée que l'existante, qui est simplement un peu bugguée.
Rome ne s'est pas construite en un jour, et de la même manière, un programme ne peut être parfait du premier coup, il faut le revoir maintes et maintes fois. Ne pas accepter de critique sur son travail, c'est simplement être incapable de progresser.
Bien cordialement.
En proposant une solution au problème, j'ai donc réagit de la façon à laquelle je m'étais habitué depuis quelques jours : donner des pistes simples qui satisfont les esprits superficiels ou peu scrupuleux.
De ton coté, tu as le courage de proposer mieux, mais très franchement la plupart des intervenants ici ne mérite pas tant de considération.
Enfin bon, je crois que je vais regagner mes Pénates, ces trois jours furent enrichissants mais loin de mes attentes en matière de qualité de tutorat.
Bon courage pour la suite.
Tu as tout à fait raison quand à l'attitude d'une majorité des gens qui postent ici. Et c'est regrettable à dire. C'est malheureusement l'inconvénient majeur d'un forum sur lesquels les invités peuvent poster sans identification.
Personnellement je ne réponds intelligemment qu'aux personnes qui font un minimum d'effort : la politesse est le point essentiel, l'orthographe étant selon moi aussi une marque de respect, j'y attache de l'importance.
Beaucoup de gens pensent qu'être informaticien c'est facile : on trouve tout sur internet. Si c'était le cas, les diverses formations dans le domaine n'auraient plus aucun intérêt. C'est en partie pour montrer que ce n'est pas à la portée du premier venu que je m'applique dans mes projets : ce n'est pas en lisant le premier tutoriel venu sur un langage quelconque que l'on sait programmer.
J'ai lu quelques uns de tes posts, et tu as parfaitement raison lorsque pour certains problèmes tu aiguilles les personnes en fournissant un lien judicieux. Si cela peut suffire, alors tant mieux. Mais parfois certains problèmes ne sont pas triviaux et méritent qu'on se penche dessus.
Personnellement si j'essaie d'aider les gens ici, c'est non seulement pour eux, mais aussi pour moi, car me pencher sur leur problème peut parfois être enrichissant.
Enfin, je suis de ton avis : si tu recherches des défis techniques ou encore le respect que tu mérites, ici c'est loin d'être le paradis et tu trouveras bien mieux sur des forums spécialisés. En espérant que tu trouves ton bonheur.
Cordialement