具有多个操作的Java计算器

时间:2012-09-16 16:03:39

标签: java math calculator equation-solving

到目前为止我有以下工作正常。我确定可能有一种更简单的方法可以做到这一点,但我需要改变/改变的是Matheq的顶级方法。 Math方法执行单个数学运算。

它适用于带有+, - ,*和/.

的任何单个操作

我的问题是解决一个更大的等式,如10 - 10/5 + 3。 然而,它确实正确地解决了10/5 + 65 * 2。 原因是每个部分,数字和操作都被拆分为字符串数组。每次操作完成后,数字和操作将替换为该等式的结果。可能看起来更令人困惑,但我想不出更好的方法。它无法解决其他方程的原因是因为我将字符串映射回字符串数组。

字符串数组的示例 防爆。 10 - 10/5 + 3 String = {10, - ,10,/,5,+,3} 在操作之后先进行除法,然后从左到右减去然后加法 String = {8,8,2,2,2,5,5}

这是我的代码,有人请帮助我:

REVISED 的 修改,现在它适用于上面,但仍然有一些LONG方程的麻烦。 一个简短的例子是它解决了2 * 2 * 2 * 2除以5就好了但是如果改变的话 10 - 2 * 2 * 2 * 2除以5我得错了答案。

 public class Matheq {

String fnum = null;
String lnum = null;
String total = null;

public String Matheq(String mathoperation) {

    String mathoperation= "6 * 3 - 4 * 2";

    mathoperation = mathoperation.replaceAll(",", "");
    mathoperation = mathoperation.replaceAll("plus", "+");
    mathoperation = mathoperation.replaceAll("minus", "-");
    mathoperation = mathoperation.replaceAll("times", "*");
    mathoperation = mathoperation.replaceAll("divided by", "dividedby");
    mathoperation = mathoperation.replaceAll("percent of", "percentof");
    String[] splitstr = mathoperation.split(" ");
    while(splitstr.length>1){
    for(int i=0; i<splitstr.length; i++) {
        System.out.println("Get value: " + splitstr[i]);
        if(splitstr[i].indexOf("percentof") >= 0) {
        String buildit = splitstr[i-1] + " percent of " + splitstr[i+1];
        String done = math(buildit);
        System.out.println("Percentage operation: " + splitstr[i-1] + " percent of " + splitstr[i+1] + "=" + done);
        splitstr[i] = done;
        splitstr[i-1] = "";
        splitstr[i+1] = "";
        ArrayList<String> list = new ArrayList<String>();
        for(String s : splitstr){
            if(!s.equals("")){
                list.add(s);
            }
        }
        splitstr = list.toArray(new String[list.size()]);
        }
    }
    for(int i=0; i<splitstr.length; i++) {
        System.out.println("Get value: " + splitstr[i]);
        if(splitstr[i].indexOf("dividedby") >= 0) {
            String buildit = splitstr[i-1] + " divided by " + splitstr[i+1];
            String done = math(buildit);
            System.out.println("Division operation: " + splitstr[i-1] + " divided by " + splitstr[i+1] + "=" + done);
            splitstr[i] = done;
            splitstr[i-1] = "";
            splitstr[i+1] = "";
            ArrayList<String> list = new ArrayList<String>();
            for(String s : splitstr){
                if(!s.equals("")){
                    list.add(s);
                }
            }
            splitstr = list.toArray(new String[list.size()]);
        }
    }
    for(int i=0; i<splitstr.length; i++) {
        System.out.println("Get value: " + splitstr[i]);
        if(splitstr[i].indexOf("*") >= 0) {
            String buildit = splitstr[i-1] + " * " + splitstr[i+1];
            String done = math(buildit);
            System.out.println("Multiplication operation: "+ splitstr[i-1] + " * " + splitstr[i+1] + "=" + done);
            splitstr[i] = done;
            splitstr[i-1] = "";
            splitstr[i+1] = "";
            ArrayList<String> list = new ArrayList<String>();
            for(String s : splitstr){
                if(!s.equals("")){
                    list.add(s);
                }
            }
            splitstr = list.toArray(new String[list.size()]);
        }
    }
    for(int i=0; i<splitstr.length; i++) {
            System.out.println("Get value: " + splitstr[i]);
        if(splitstr[i].indexOf("+") >= 0) {
            String buildit = splitstr[i-1] + " + " + splitstr[i+1];
            String done = math(buildit);
            System.out.println("Addition operation: " + splitstr[i-1] + " + " + splitstr[i+1] + "=" + done);
            splitstr[i] = done;
            splitstr[i-1] = "";
            splitstr[i+1] = "";
            ArrayList<String> list = new ArrayList<String>();
            for(String s : splitstr){
                if(!s.equals("")){
                    list.add(s);
                }
            }
            splitstr = list.toArray(new String[list.size()]);
        }
    }
        for(int i=0; i<splitstr.length; i++) {
            System.out.println("Get value: " + splitstr[i]);
            if(splitstr[i].indexOf("-") >= 0) {
            String buildit = splitstr[i-1] + " - " + splitstr[i+1];
            String done = math(buildit);
            System.out.println("Subtraction operation: " + splitstr[i-1] + " - " + splitstr[i+1] + "=" + done);
            splitstr[i] = done;
            splitstr[i-1] = "";
            splitstr[i+1] = "";
            ArrayList<String> list = new ArrayList<String>();
            for(String s : splitstr){
                if(!s.equals("")){
                    list.add(s);
                }
            }
            splitstr = list.toArray(new String[list.size()]);
        }   
    }
    for(int i=0; i<splitstr.length; i++) {  
        System.out.println("Final operation: " + total + " " + splitstr[i]);
    }
    }
    return total;

}

private String math(String mathoperation) {
    // TODO Auto-generated method stub
    if(mathoperation.contains("percent of")){
        mathoperation = mathoperation.replaceAll("percent of", "%");
        int str = mathoperation.indexOf("%");
        System.out.println(str);
        fnum = mathoperation.substring(0, str-1);
        fnum = fnum.replaceAll(" ", "");
        fnum = "." + fnum;
        System.out.println(fnum);
        double intfnum = Double.parseDouble(fnum);
        System.out.println(intfnum);
        int lastind = mathoperation.length();
        System.out.println(lastind);
        lnum = mathoperation.substring(str+1, lastind);
        lnum = lnum.replaceAll(" ", "");
        System.out.println(lnum);
        double intlnum = Double.parseDouble(lnum);
        System.out.println(intlnum);
        double tot = intlnum * intfnum;
        System.out.println(tot);
        total = Double.toString(tot);
        if(total.length() == 3){
            total = total + "0";
        }
        if(total.length() > 5){
            total = total.substring(0, 4);
        }
        total = total.replace("0.", "");
        System.out.println("Total:" + total);
        } else 
    if(mathoperation.contains("-")){
        int str = mathoperation.indexOf("-");
        System.out.println(str);
        fnum = mathoperation.substring(0, str-1);
        fnum = fnum.replaceAll(" ", "");
        System.out.println(fnum);
        double intfnum = Double.parseDouble(fnum);
        System.out.println(intfnum);
        int lastind = mathoperation.length();
        System.out.println(lastind);
        lnum = mathoperation.substring(str+1, lastind);
        lnum = lnum.replaceAll(" ", "");
        System.out.println(lnum);
        double intlnum = Double.parseDouble(lnum);
        System.out.println(intlnum);
        double tot = intfnum - intlnum; 
        System.out.println(tot);
        total = Double.toString(tot);
        System.out.println(total);
        } else 
    if(mathoperation.contains("+")){
        int str = mathoperation.indexOf("+");
        System.out.println(str);
        fnum = mathoperation.substring(0, str-1);
        fnum = fnum.replaceAll(" ", "");
        System.out.println(fnum);
        double intfnum = Double.parseDouble(fnum);
        System.out.println(intfnum);
        int lastind = mathoperation.length();
        System.out.println(lastind);
        lnum = mathoperation.substring(str+1, lastind);
        lnum = lnum.replaceAll(" ", "");
        System.out.println(lnum);
        double intlnum = Double.parseDouble(lnum);
        System.out.println(intlnum);
        double tot = intfnum + intlnum; 
        System.out.println(tot);
        total = Double.toString(tot);
        System.out.println(total);
        } else 
    if(mathoperation.contains("*")){
    int str = mathoperation.indexOf("*");
    System.out.println(str);
    fnum = mathoperation.substring(0, str-1);
    fnum = fnum.replaceAll(" ", "");
    System.out.println(fnum);
    double intfnum = Double.parseDouble(fnum);
    System.out.println(intfnum);
    int lastind = mathoperation.length();
    System.out.println(lastind);
    lnum = mathoperation.substring(str+1, lastind);
    lnum = lnum.replaceAll(" ", "");
    System.out.println(lnum);
    double intlnum = Double.parseDouble(lnum);
    System.out.println(intlnum);
    double tot = intfnum * intlnum; 
    System.out.println(tot);
    total = Double.toString(tot);
    System.out.println(total);
    } else
    if(mathoperation.contains("divided by")){
    mathoperation = mathoperation.replaceAll("divided by", "/");
    int str = mathoperation.indexOf("/");
    System.out.println(str);
    fnum = mathoperation.substring(0, str-1);
    fnum = fnum.replaceAll(" ", "");
    System.out.println(fnum);
    double intfnum = Double.parseDouble(fnum);
    System.out.println(intfnum);
    int lastind = mathoperation.length();
    System.out.println(lastind);
    lnum = mathoperation.substring(str+1, lastind);
    lnum = lnum.replaceAll(" ", "");
    System.out.println(lnum);
    double intlnum = Double.parseDouble(lnum);
    System.out.println(intlnum);
    double tot = intfnum / intlnum; 
    System.out.println(tot);
    total = Double.toString(tot);
    System.out.println(total);
    } else {
        total = null;
    }
    return total;
}

}

3 个答案:

答案 0 :(得分:9)

数组是表示解析方程的错误结构。您需要具有可以表示运算符优先级的结构。处理此类问题的典型机制是abstract syntax tree。对于10 - 10/5 + 3示例,您可能希望构建一个如下所示的树:

 <result>
  /   \
 '-' '+'
 / \ / \
10 '/'  3
   / \
  10  5

这种具有高优先级操作符的结构会降低树的结构,然后您可以执行自下而上的评估以获得正确的结果。

答案 1 :(得分:4)

您所要做的就是将前缀输入转换为后缀格式。然后你可以使用堆栈轻松完成魔法。我使用命令模式编写了一个完整的解决方案。

将中缀转换为后缀的方法

    public static List<String> infixToPostfixConvert(String input) {

    int priority = 0;
    String postfixBuffer = "";
    Stack<Character> stack = new Stack<Character>();
    List<String> postfixArray = new ArrayList<String>();

    for (int i = 0; i < input.length(); i++) {
        char ch = input.charAt(i);
        if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {

            if (postfixBuffer.length() > 0) {
                postfixArray.add(postfixBuffer);
            }
            postfixBuffer = "";
            // check the precedence
            if (stack.size() <= 0)
                stack.push(ch);
            else {
                Character chTop = (Character) stack.peek();
                if (chTop == '*' || chTop == '/')
                    priority = 1;
                else
                    priority = 0;
                if (priority == 1) {
                    if (ch == '+' || ch == '-') {
                        postfixArray.add(String.valueOf(stack.pop()));
                        i--;
                    } else { // Same
                        postfixArray.add(String.valueOf(stack.pop()));
                        i--;
                    }
                } else {
                    if (ch == '+' || ch == '-') {
                        postfixArray.add(String.valueOf(stack.pop()));
                        stack.push(ch);
                    } else
                        stack.push(ch);
                }
            }
        } else {
            postfixBuffer += ch;
        }
    }
    postfixArray.add(postfixBuffer);
    int len = stack.size();
    for (int j = 0; j < len; j++)
        postfixArray.add(stack.pop().toString());

    return postfixArray;
}

然后我有另一个使用Calculator实例并传递后缀字符串的方法。

    public void calculate(Calculator cal, List<String> postFix) {

    Stack<BigDecimal> stack = new Stack<BigDecimal>();

    for ( int i = 0; i < postFix.size(); i++ ) {

        String next = postFix.get(i);

        if (next.equals("+") || next.equals("-") || next.equals("*")
                || next.equals("/")) {
            ArithmaticCalculatorCommand cmd = new ArithmaticCalculatorCommand(
                    next.charAt(0), stack.pop(), stack.pop(), cal);
            Invoker invoker = new Invoker();
            invoker.compute(cmd);
            stack.push(cal.getCurrent());
        } else if ( false ){

        }
        else
        {
            stack.push(new BigDecimal(next.trim()));
        }
    }
}

完成实施

命令接口

package org.sanjaya;
public interface Command {

    public void calculate();
}

命令实现

package org.sanjaya.impl;

import java.math.BigDecimal;

import org.sanjaya.Command;

public class ArithmaticCalculatorCommand implements Command {

    private char operator;
    private BigDecimal leftOperand;
    private BigDecimal rightOperand;
    private Calculator calculator;

    public ArithmaticCalculatorCommand( char operator, BigDecimal leftOperand, BigDecimal rightOperand, Calculator calculator ) {
        this.leftOperand = leftOperand;
        this.rightOperand = rightOperand;
        this.operator = operator;
        this.calculator = calculator;
    }

    /*
     * This method invoke the three argument operation method that is only used for arithmetic calculations.
     * @param operator
     * @param leftOperand
     * @param rightOperand   * 
     * @see org.sanjaya.Command#calculate()
     */
    public void calculate() {
        calculator.operation( operator, leftOperand, rightOperand );        
    }   
}

计算器类(接收器)

package org.sanjaya.impl;

import java.math.BigDecimal;

public class Calculator {

    private static Calculator calculator;   
    private BigDecimal current = new BigDecimal( 0 );

    private Calculator()
    {

    }

    public static Calculator getInstance()
    {
        if ( calculator == null )
        {
            calculator = new Calculator();
        }
        return calculator;
    }

    /*
     * This method calculate current value for any number of calculation operations.
     * Currently following operations are supported
     * +,-,*,/
     * 
     * @param operator
     * @param leftOperand
     * @param rightOperand
     *  
     */
    public void operation( char operator, BigDecimal leftOperand, BigDecimal rightOperand )
    {       
        switch ( operator )
        {
        case '+':
            current = leftOperand.add( rightOperand );
            break;
        case '-':
            current = rightOperand.subtract( leftOperand );
            break;
        case '/':
            current = rightOperand.divide(leftOperand);
            break;
        case '*':
            current = leftOperand.multiply( rightOperand );
            break;
        default:
            break;
        }       
    }

    public BigDecimal getCurrent() {
        return current;
    }

    public void setCurrent(BigDecimal current) {
        this.current = current;
    }

}

祈求者类

package org.sanjaya.impl;

import java.math.BigDecimal;

import org.sanjaya.Command;
public class Invoker {

    public void compute( Command command )
    {
        command.calculate();
    }   
}

客户等级

package org.sanjaya.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import java.util.logging.Logger;
public class CalculatorParser {

    public static Logger logger = Logger.getLogger( "Calculator_Logger" );

    public static void main( String a [] )
    {
        new CalculatorParser().start();
    }

    /*
     * This is the starting point of the program. It receives input from the command line 
     * and process them further and sends to calculate function. At the end this method 
     * displays the calculated result.
     */
    public void start()
    {
        Scanner scanner = new Scanner( System.in );
        logger.info("\n\t Please input expression to calculate::");

        String line = scanner.nextLine();
        List<String> postfixString = CalculatorParser.infixToPostfixConvert( line );
        Calculator calculator = Calculator.getInstance();
        calculator.setCurrent( new BigDecimal( 0 ) );

        calculate( calculator, postfixString );

        logger.info("Result is " + calculator.getCurrent() );
    }

    /*
     * This method keeps a stack to process postfix version of the input and execute the right command implementation.
     * Currently this method supports for arithmetic command calculations only.
     * @param Cal
     * @param postFix
     */
    public void calculate(Calculator cal, List<String> postFix) {

        Stack<BigDecimal> stack = new Stack<BigDecimal>();

        for ( int i = 0; i < postFix.size(); i++ ) {

            String next = postFix.get(i);

            if (next.equals("+") || next.equals("-") || next.equals("*")
                    || next.equals("/")) {
                ArithmaticCalculatorCommand cmd = new ArithmaticCalculatorCommand(
                        next.charAt(0), stack.pop(), stack.pop(), cal);
                Invoker invoker = new Invoker();
                invoker.compute(cmd);
                stack.push(cal.getCurrent());
            } else if ( false ){

            }
            else
            {
                stack.push(new BigDecimal(next.trim()));
            }
        }
    }

    /*
     * This method convert the infix into postfix in order to proceed in the calculation.
     * @param input 
     */
    public static List<String> infixToPostfixConvert(String input) {

        int priority = 0;
        String postfixBuffer = "";
        Stack<Character> stack = new Stack<Character>();
        List<String> postfixArray = new ArrayList<String>();

        for (int i = 0; i < input.length(); i++) {
            char ch = input.charAt(i);
            if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {

                if (postfixBuffer.length() > 0) {
                    postfixArray.add(postfixBuffer);
                }
                postfixBuffer = "";
                // check the precedence
                if (stack.size() <= 0)
                    stack.push(ch);
                else {
                    Character chTop = (Character) stack.peek();
                    if (chTop == '*' || chTop == '/')
                        priority = 1;
                    else
                        priority = 0;
                    if (priority == 1) {
                        if (ch == '+' || ch == '-') {
                            postfixArray.add(String.valueOf(stack.pop()));
                            i--;
                        } else { // Same
                            postfixArray.add(String.valueOf(stack.pop()));
                            i--;
                        }
                    } else {
                        if (ch == '+' || ch == '-') {
                            postfixArray.add(String.valueOf(stack.pop()));
                            stack.push(ch);
                        } else
                            stack.push(ch);
                    }
                }
            } else {
                postfixBuffer += ch;
            }
        }
        postfixArray.add(postfixBuffer);
        int len = stack.size();
        for (int j = 0; j < len; j++)
            postfixArray.add(stack.pop().toString());

        return postfixArray;
    }
}

答案 2 :(得分:0)

我没有使点工作,这是另一天。

mainlaunch中的

让按钮将其文本发送到我们的buttonHandler。

buttons.get(i).setOnAction(ev -> buttonHandler(text))

在方法中:

  • 如果该文字是数字,只需附加它。
  • 如果是操作员将其添加到堆栈中。
  • 如果堆栈上有*或/,则执行计算并将新号码添加到堆栈中。
  • 最后,堆栈上只有+和 -
  • 计算结果。

代码:

private void buttonHandler(String buttonValue) {
    String newInput = tfInput.getText();

    switch (buttonValue) {
        default:
            // If a previous calculation was made, reset input.
            if (lastOperator.equals("=")) {
                lInput.setText("");
                tfInput.setText(buttonValue);

            // else append the new input.
            } else {
                tfInput.appendText(buttonValue);
            }
            break;
        case " ":
            break;
        case ".":
            if(!input.contains(".")) {
                tfInput.appendText(buttonValue);
            }
            break;
        case "DEL":
            try {
                tfInput.setText("" + newInput.substring(0, tfInput.getText().length() - 1));
            } catch (Exception ex) { }
            break;

        // Operators
        case "x":
        case "/":
        case "+":
        case "-":
        case "=":

            if (newInput.length() > 0) {
                lInput.setText(lInput.getText() + newInput + " " + buttonValue + " ");

                try {
                    // If the previous operator has priority, make a calculation and push to stack
                    if (!input.empty()) {
                        if (input.peek().equals("x")) {
                            input.pop();
                            newInput = new BigDecimal(input.pop()).multiply(new BigDecimal(newInput)).toString();
                        } else if (input.peek().equals("/")) {
                            input.pop();
                            newInput = new BigDecimal(input.pop()).divide(new BigDecimal(newInput), 3, RoundingMode.HALF_UP).stripTrailingZeros().toString();
                            System.out.println(newInput);
                        }
                    }
                } catch (Exception ex) {
                    System.out.println("something is this part went wrong");
                }

                // If the "=" wasn't pressed, add input to the stack and set the textfield empty.
                if (!buttonValue.equals("=")) {
                    // Push to stack and empty input.
                    input.push(newInput);
                    input.push(buttonValue);
                    tfInput.setText("");

                // The button is "=". Prepare for final calculation
                } else {
                    if(!input.empty()) {
                        try {
                            // Reverse items.
                            Stack<String> stack = new Stack<>();
                            stack.push(newInput);
                            while (!input.empty()) {
                                stack.push(input.pop());
                            }

                            // Perform final calculation.
                            while (!stack.empty()) {
                                String firstNumber = stack.pop();
                                if (stack.peek().equals("+")) {
                                    stack.pop();
                                    newInput = new BigDecimal(firstNumber).add(new BigDecimal(stack.pop())).toString();
                                } else if (stack.peek().equals("-")) {
                                    stack.pop();
                                    newInput = new BigDecimal(firstNumber).subtract(new BigDecimal(stack.pop())).toString();
                                }
                                if (!stack.empty()) {
                                    stack.push(newInput);
                                } else {
                                    tfInput.setText(newInput);
                                }
                            }

                        } catch (Exception ex) {
                            System.out.println("something in the second part went wrong");
                        }
                    } else {
                        tfInput.setText(newInput);
                    }
                }
            }
    }
    lastOperator = buttonValue;
}

如果你想在&#39;发布&#39;中计算一个像这样的字符串。 mehtod:

 String test = "10-10/5+3=";
    for (int i = 0; i < test.length(); i++) {
        buttonHandler(test.charAt(i) + "");
    }