Calculatrice Rpn
Résolu/Fermé
etbienwi
Messages postés
18
Date d'inscription
lundi 16 octobre 2017
Statut
Membre
Dernière intervention
22 mai 2018
-
Modifié le 5 nov. 2017 à 12:42
etbienwi Messages postés 18 Date d'inscription lundi 16 octobre 2017 Statut Membre Dernière intervention 22 mai 2018 - 7 nov. 2017 à 22:28
etbienwi Messages postés 18 Date d'inscription lundi 16 octobre 2017 Statut Membre Dernière intervention 22 mai 2018 - 7 nov. 2017 à 22:28
A voir également:
- Calculatrice rpn en ligne
- Partager photos en ligne - Guide
- Site de vente en ligne particulier - Guide
- Aller à la ligne excel - Guide
- Test performance pc en ligne - Guide
- Installer calculatrice sur mon portable - Télécharger - Calcul & Conversion
1 réponse
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
5 nov. 2017 à 13:24
5 nov. 2017 à 13:24
Bonjour,
Je trouve maladroit de faire une méthode abstract dans l'enum et faire autant de classes concrètes que de valeurs de l'enum.
Il y a des alternatives plus intéressantes.
Ou en Java 8 ou 9 :
Quant à ton moteur, tu ne peux pas stocker que les opérandes dans ta stack, il faut aussi stocker les opérateurs.
Exemple :
Pour faire ça il faudrait que tu ais une interface (par exemple Token) partagée entre ton enum Operations (qu'il serait sage de renommer Operator) et une classe Operand, et que dans ta pile tu ne manipules que des Token (alternativement des Operator et ses Operand)
Exemple :
Je trouve maladroit de faire une méthode abstract dans l'enum et faire autant de classes concrètes que de valeurs de l'enum.
Il y a des alternatives plus intéressantes.
package calculatrice; public enum Operations { PLUS("+"), MOINS("-"), MULT("*"), DIV("/"); private String symbole; private Operations(String s) { symbole = s; } public final double eval(double x, double y) { switch (this) { case PLUS: return x + y; case MOINS: return x - y; case MULT: return x * y; case DIV: return x / y; default: throw new IllegalStateException("eval(double,double) is not implemented for " + this); } } };
Ou en Java 8 ou 9 :
package calculatrice; import java.util.function.BiFunction; public enum Operations { PLUS("+", (x, y) -> x + y), MOINS("-", (x, y) -> x - y), MULT("*", (x, y) -> x * y), DIV("/", (x, y) -> x / y); private final String symbole; private final BiFunction<Double, Double, Double> function; private Operations(String s, BiFunction<Double, Double, Double> function) { symbole = s; this.function = function; } public double eval(double x, double y) { return function.apply(x, y); } };
Quant à ton moteur, tu ne peux pas stocker que les opérandes dans ta stack, il faut aussi stocker les opérateurs.
Exemple :
MOINS PLUS 3 4 1qui donne
Moins(Plus(3,4),1)c'est à dire (3+4)-1
Pour faire ça il faudrait que tu ais une interface (par exemple Token) partagée entre ton enum Operations (qu'il serait sage de renommer Operator) et une classe Operand, et que dans ta pile tu ne manipules que des Token (alternativement des Operator et ses Operand)
Exemple :
public enum TokenType { OPERAND, OPERATOR }
public interface Token { TokenType getType(); }
public class Operand implements Token { private final double value; public Operand(double value) { this.value = value; } public double getValue() { return value; } @Override public TokenType getType() { return TokenType.OPERAND; } }
public enum Operator implements Token { PLUS((x, y) -> x + y), MOINS((x, y) -> x - y), MULT((x, y) -> x * y), DIV((x, y) -> x / y); private final BiFunction<Double, Double, Double> function; private Operator(BiFunction<Double, Double, Double> function) { this.function = function; } public Operand eval(Operand x, Operand y) { return new Operand(function.apply(x.getValue(), y.getValue())); } @Override public TokenType getType() { return TokenType.OPERATOR; } };
public static Operand nextOperand(Stack<Token> tokens) { Token token = tokens.pop(); switch (token.getType()) { case OPERAND: return (Operand) token; case OPERATOR: Operand op1 = nextOperand(tokens); Operand op2 = nextOperand(tokens); return ((Operator) token).eval(op1, op2); default: throw new IllegalStateException("Unknown " + token.getType()); } } public static void main(String[] args) { Stack<Token> tokens = new Stack<Token>(); tokens.push(new Operand(1)); tokens.push(new Operand(4)); tokens.push(new Operand(3)); tokens.push(Operator.PLUS); tokens.push(Operator.MOINS); System.out.println(nextOperand(tokens).getValue()); // 6.0 }
6 nov. 2017 à 11:05
Je ne savais pas comment mettre dans la pile les opérandes et les opérateurs, c'est la première fois que j'utilise des énumérations. Par contre je ne comprend pas bien ces deux éléments:
Je vois bien ce qu'ils permettent de faire mais je ne serai pas capable de refaire un truc semblable(c'est un peu flou...)
J'ai essayé de faire une méthode pour afficher toutes mes opérandes:
elle affiche les opérators mais pour les chiffres elle m'affiche :
Merci d'avance.
6 nov. 2017 à 13:18
C'est parce que la méthode toString n'est pas redéfini dans la classe Operand (alors qu'elle l'est dans les enum).
Remarque : tu peux faire directement, ça marche aussi, et ça évite de faire un pop() qui va supprimer les valeurs de ta pile...
"je ne comprend pas bien ces deux éléments"
est une interface qui possède une méthode ce qui correspond bien à ce que tu souhaites faire avec tes opérateurs.
À voir : java.util.function.BiFunction<T,U,R>
Comme c'est une interface qui n'a qu'une seule méthode à implémenter on dit que c'est une interface fonctionnelle, ce qui permet d'utiliser des lambda comme mais on pourrait également faire comme ceci, ça passerait à la compilation, ça reviendrait à ton code de départ, mais c'est moins performant :
NB. On pourrait également faire des références de méthodes.
À voir : Java - Les Structures fonctionnelles
Dans la suite, le est une application directe de cette fonction, il faut juste faire la conversion entre les types Double et Operand.
Remarque : ce n'est pas forcément utile ici, mais si on voulait être bien propre, je ferai implémenter la classe Operator de l'interface BiFunction, il faudrait juste renommer la méthode eval(x,y) en apply(x,y).
6 nov. 2017 à 23:38
Merci beaucoup, avec les exemples j'ai bien compris maintenant comme cela fonctionne( Grace aux liens je vais pouvoir approfondir ).
Je veux essayer maintenant d'utiliser la classe scanner de java.util pour entrer mes opérandes et faire le calcul. J'ai fait une autre classe qui est sensé utiliser la classe opérande. Cette dernière fait déjà tout le travail et je ne sais pas comment les lier.
J'ai obtenu cela:
Est ce c'est de cette manière que l'on est sensé le faire?
Merci d'avance.
Modifié le 7 nov. 2017 à 00:00
7 nov. 2017 à 15:26
J'ai voulu utiliser la même méthode que pour le nextOperand mais je ne m'en sors pas vraiment.
comment faire pour que ce qui rentre en paramètre puisse être considéré comme une Opérande ou un Opérateur.