具有多种操作的Java计算器

新手上路,请多包涵

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

它确实适用于 +、-、\* 和 / 的任何单个操作。

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

字符串数组示例 Ex。 with 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;
}

}

原文由 itgeek25 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 352
2 个回答

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

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

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

原文由 Michael Barker 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

中缀转后缀的方法

    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;
}

然后我有另一种方法使用计算器实例并传递后缀字符串。

     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;
    }
}

原文由 Sanjaya Athukorala 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题