Publié le 30/09/2010
Auteur axel
Réseaux sociaux
0 partages
0 tweets
0 plus
0 commentaires

Calculer le resultat d'une operation mathematique

A partir d'une série d'opérations mathématiques, la class EquationSolver calcule le résultat numérique. Toutes les opérations de bases sont supportées:
- addition, soustraction,
- multiplication, division.

Interpreteur mathematique

L'auteur Mark Alexander Edwards a fait évoluer l'interpréteur mathématique en y ajoutant les nombres comportant des décimales et les valeurs négatives.
import java.util.*;
import java.io.*;
import java.text.*;
import java.math.*;
 
/****************************************
 * @Author: Mark Alexander Edwards Jr.
 *
 * Utility class for solving equations.
 ****************************************/
public final class EquationSolver {    // Utility classes don't need extensions!
 
    private EquationSolver() {
    }    // Utility classes don't need to be instantiated!
 
    /*Constants*/
    private static final Character POW = new Character('^');
    private static final Character MUL = new Character('*');
    private static final Character DIV = new Character('/');
    private static final Character MOD = new Character('%');
    private static final Character ADD = new Character('+');
    private static final Character[] firstSet = {POW}, secondSet = {MUL, DIV, MOD}, thirdSet = {ADD};
    private static final DecimalFormat DF = new DecimalFormat();
    private static final StringBuffer SB = new StringBuffer();
    private static final MathContext MC = new MathContext(40);
 
    private enum Direction {
 
        L_TO_R,
        R_TO_L
    };
 
    /**
     * A Means of testing the program.
     */
    public static void main(String... args) {
        System.out.println();
        System.out.println(EquationSolver.solve("5 + 3 * (8 - 4)"));
        System.out.println();
        System.out.println(EquationSolver.solve("12 / (3 * 4) + 5"));
        System.out.println();
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        while (true) {
            System.out.print("Enter an equation you would like to solve n(or enter EXIT to exit program): ");
            try {
                String temp = br.readLine();
 
                if (temp.equalsIgnoreCase("exit")) {
                    try {
                        isr.close();
                        br.close();
                    } catch (Exception f) {
                    } finally {
                        System.exit(0);
                    }
                }
 
                long t1 = System.nanoTime();
                System.out.println("Answer: " + EquationSolver.solve(temp, 4));
                long t2 = System.nanoTime();
                System.out.println("nTime taken to calculate value: " + (t2 - t1) + " nanoseconds");
            } catch (Exception e) {
            }
        }
    }
 
    /**
     * Performs an operation on the two numbers specified
     */
    private static String doOperation(String lhs, char operator, String rhs) {
        BigDecimal bdLhs = new BigDecimal(lhs);
        BigDecimal bdRhs = new BigDecimal(rhs);
        switch (operator) {
            case '^':
                return "" + Math.pow(bdLhs.doubleValue(), bdRhs.doubleValue());
            case '*':
                return "" + bdLhs.multiply(bdRhs).toString();
            case '/':
                return "" + bdLhs.divide(bdRhs, MC).toString();
            case '+':
                return "" + bdLhs.add(bdRhs).toString();
            case '%':
                return "" + bdLhs.remainder(bdRhs).toString();
        }
        return "";
    }
 
    /**
     * Returns a corrected version of the String, which is one that
     * has its first and last paranthesis removed.
     */
    private static String correctedString(String arg) {
 
        StringBuilder sb = new StringBuilder(); // A Mutable String
        boolean foundFirst = false;
        for (int i = 0; i < arg.length(); i++) {
            if (foundFirst == false && arg.charAt(i) == '(') {
                foundFirst = true;
            } else {
                sb.append(arg.charAt(i));
            }
        }
 
        arg = new StringBuilder(sb.reverse()).toString();
        sb.delete(0, sb.length());
 
        foundFirst = false;
        for (int i = 0; i < arg.length(); i++) {
            if (foundFirst == false && arg.charAt(i) == ')') {
                foundFirst = true;
            } else {
                sb.append(arg.charAt(i));
            }
        }
 
        return arg = new StringBuilder(sb.reverse()).toString();
    }
 
    /**
     * Provides a means of halting a process for a specified amount of time
     * without directly using the static Thread method sleep.
     *
     * Used for debugging purposes
     */
    private static void sleep(int mill) {
        long t1 = System.currentTimeMillis();
        long t2 = t1 + mill;
        while ((t1 = System.currentTimeMillis()) < t2);
    }
 
    /**
     * Returns the a String that all of the characters the parameter argu
     * has, minus the space characters in the String
     */
    private static String removeSpaces(String argu) {
        String temp = "";
 
        for (int i = 0; i < argu.length(); i++) {
            if (argu.charAt(i) != ' ') {
                temp += "" + argu.charAt(i);
            }
        }
 
        return temp;
    }
 
    /**
     * Contains an expression that exists within parenthesis
     * i.e., (5+3), (6 + 2), etc.
     *
     * If a set of paranethesis exists within the expression, it must be resolved
     * by using another expression object to solve the inner expression.
     * i.e., (5 + 3 - 2 + (8 * 7) ) would first result in an ExpressionNode consisting of
     * a call to another expression to Solve the inner expression
     *
     * Returns the result of the calculated ExpressionNode.
     * If another expression is found within this one,
     * a new ExpressionNode will be created and will solve
     * the inner expression.
     */
    private static String parse(String arg) {
 
        String expression = removeSpaces(correctedString(arg));
        String finalExpression = "";
        boolean operatorEncountered = true;
        boolean initialValue = true;
        for (int i = 0; i < expression.length(); i++) {
            if (expression.charAt(i) == '(') {
                String multiply = "";
                if (operatorEncountered == false && initialValue == false) {
                    multiply += "*";
                }
 
                String placeHolder = "(";
                int valuesCounted = 1;
                operatorEncountered = false;
                for (int j = i + 1; valuesCounted != 0; j++) {
                    if (expression.charAt(j) == '(') {
                        valuesCounted++;
                    } else if (expression.charAt(j) == ')') {
                        valuesCounted--;
                    }
                    placeHolder += "" + expression.charAt(j);
                }
 
                String evaluatedString = parse(placeHolder);
                finalExpression += multiply + evaluatedString;
                i += (placeHolder.length() - 1);
            } else {
                if (expression.charAt(i) == '-' && operatorEncountered == false) {
                    finalExpression += ((!initialValue) ? "+" : "") + expression.charAt(i);
                } else if (expression.charAt(i) == '-' && operatorEncountered == true) {
                    finalExpression += "-1*";
                } else {
                    finalExpression += expression.charAt(i);
                }
 
                if ((expression.charAt(i) == '+'
                        || expression.charAt(i) == '/'
                        || expression.charAt(i) == '^'
                        || expression.charAt(i) == '*'
                        || expression.charAt(i) == '%'
                        || expression.charAt(i) == '-')) {
                    operatorEncountered = true;
                } else if (expression.charAt(i) != ' ') {
                    operatorEncountered = false;
                }
            }
            initialValue = false;
        }
 
        finalExpression = removeSpaces(finalExpression);
        String perfectExpression = "";
 
        for (int i = 0; i < finalExpression.length(); i++) {
            if ((i + 1) < finalExpression.length()) {
                if (finalExpression.charAt(i) == '-' && finalExpression.charAt(i + 1) == '-') {
                    i += 2;
                }
            }
            perfectExpression += "" + finalExpression.charAt(i);
        }
        finalExpression = perfectExpression;
 
        ArrayList<String> totalNumbers = new ArrayList<String>(0);
        ArrayList<Character> totalOperations = new ArrayList<Character>(0);
        System.out.println(finalExpression);
 
        for (int i = 0; i < finalExpression.length(); i++) {
            if (finalExpression.charAt(i) >= '0' && finalExpression.charAt(i) <= '9'
                    || finalExpression.charAt(i) == '-' || finalExpression.charAt(i) == '.'
                    || finalExpression.charAt(i) == ',') {
                String temp = "";
                for (int j = i; j < finalExpression.length(); j++) {
                    if (finalExpression.charAt(j) >= '0' && finalExpression.charAt(j) <= '9'
                            || finalExpression.charAt(j) == '-' || finalExpression.charAt(j) == '.'
                            || finalExpression.charAt(j) == ',') {
                        temp += "" + finalExpression.charAt(j);
                    } else {
                        break;
                    }
                }
                totalNumbers.add(temp);
                i += temp.length() == 0 ? 0 : (temp.length() - 1);
            } else if (finalExpression.charAt(i) == '*'
                    || finalExpression.charAt(i) == '/'
                    || finalExpression.charAt(i) == '^'
                    || finalExpression.charAt(i) == '+'
                    || finalExpression.charAt(i) == '%') {
                totalOperations.add(new Character(finalExpression.charAt(i)));
            }
        }
 
        calculate(totalNumbers, totalOperations, firstSet, Direction.R_TO_L);
        calculate(totalNumbers, totalOperations, secondSet, Direction.L_TO_R);
        calculate(totalNumbers, totalOperations, thirdSet, Direction.L_TO_R);
 
        return totalNumbers.get(0);
    }
 
    /**
     * Returns true if the target character exists in the set of Character operands, returns false otherwise.
     */
    private static boolean containsCharacter(Character anOperation, Character operands[]) {
        for (Character item : operands) {
            if (anOperation.equals(item)) {
                return true;
            }
        }
        return false;
    }
 
    /**
     * Attempts to solve an equation that is seperated into a set of numbers and operands.
     * (More to add)
     */
    private static void calculate(ArrayList<String> totalNumbers, ArrayList<Character> totalOperations, Character operands[], Direction dir) {
        String result = "";
        if (dir == Direction.L_TO_R) {
            for (int i = 0; i < totalOperations.size(); i++) {
                if (containsCharacter(totalOperations.get(i), operands)) {
                    result = doOperation(totalNumbers.get(i), (char) totalOperations.get(i), totalNumbers.get(i + 1));
                    totalNumbers.set(i, result);
                    totalOperations.remove(i);
                    totalNumbers.remove(i + 1);
                    i--;
                }
            }
        } else if (dir == Direction.R_TO_L) {
            for (int i = totalOperations.size() - 1; i >= 0; i--) {
                if (containsCharacter(totalOperations.get(i), operands)) {
                    result = doOperation(totalNumbers.get(i), (char) totalOperations.get(i), totalNumbers.get(i + 1));
                    totalNumbers.set(i, result);
                    totalOperations.remove(i);
                    totalNumbers.remove(i + 1);
                }
            }
        }
    }
 
    /**
     * Checks to see if the expression is solvable or not.
     *
     * This method is actually a misnomer, because more restrictions
     * should be put in place on what a user can determine as solvable.
     */
    private static boolean isSolvable(String eq) {
 
        int paranthesisCount = 0;    // assuming 0 paranthesis to begin with
        for (char element : eq.toCharArray()) {    // for every char in the String eq
            if (element == '(') // if the element is a left paranthesis
            {
                paranthesisCount++;    // increment the paranthesisCount
            } else if (element == ')') // else if the element is a right paranthesis
            {
                paranthesisCount--;    // decrement the paranthesisCount
            }
            if (paranthesisCount < 0) // if brackets aren't in correct order, return false
            {
                return false;
            }
        }
        return paranthesisCount == 0;    // return true if paranthesisCount is zero, otherwise return false
    }
 
    /**
     * Attempts to solve an equation
     */
    public static String solve(String eq) {
        if (isSolvable(eq)) {
            System.out.println(eq);    // Prints out the equation before it is parsed
            String value = "(" + eq + ")";    // Appending paranthesis to the equation for accuracy
            return parse(value); //    returning the final value of the expression
        } else {
            return "";
        }
    }
 
    /**
     * Attempts to solve an equation, with the precision factor taken into account.
     *
     * The maximum precision is 40, only because the max precision for the MathContext object is 40
     * though this is not required and can be changed in future versions.
     */
    public static String solve(String eq, int precision) {
        SB.delete(0, SB.length());
        return DF.format((double) Double.parseDouble(solve(eq)), SB, new FieldPosition(precision)).toString();    // formatted answer
    }
}


Ajouter un commentaire

Les champs marqués d'un * sont obligatoires, les adresses emails se sont pas publiées.

A lire aussi

Réseaux sociaux
Présentation de l'article
Catégorie
java - class
Mise a jour
30/09/2010
Visualisation
vu 2866 fois
Public
Internaute
Auteur de la publication
Axel
Membre junior
Auteur de 51 articles
|BIO_PSEUDO|
Commentaires récents

Publié par sakhr dans tuto

merci b c pour les plusieurs tailles d'images

Publié par Roger HENRI dans CMS

Je ne suis pas sûr que cette procédure marche toujours parfaitement à cause du mot
"selstart" qui, chez moi au moins, paraît être capricieux.

Quand je veux lire sa valeu...

Publié par snoop dans java

simple, rapide et effectif du premier coup.
Merci!

Publié par vieux dans CMS

et comment ce le procurent ton ?

Publié par samir dans CMS

merci