基于Java中的优先级重新排序数组

时间:2013-12-16 23:45:29

标签: java arrays string calculator

您好我一直在研究我的Java计算器。它现在将所有操作数和运算符放在不同的数组中,并且我还有一个具有每个运算符优先级的数组。

For example * and / are 1 and + and - are 2.
So if my operator array holds '[/, +, +, *]'
My priority array holds '[1, 2, 2, 1]'

我坚持的部分是我现在需要确保我的计算器可以重新排序运算符,这样我就可以通过我的calculateResult并确保运算符的顺序正确。

我要求帮助的部分是计算结果。我无法弄清楚如何做到这一点,以便按正确的顺序计算它。

import java.util.*;
public class stringCalculator {

    //String containing the input from the user
    private String userinput;
    //List to store the operators in
    private ArrayList<String> calcOperator = new ArrayList<String>();
    //List to store the operands in
    private ArrayList<Integer> calcOperand = new ArrayList<Integer>();
    //Array to store all the integers in
    private String[] integers;
    //Array to store all the operators in
    private String[] operators;
    //Array to store the priority value
    private String[] priorityList;

    public stringCalculator(String userinput){
        this.userinput = userinput;
        //System.out.println(userinput);
        integers = userinput.split("[+-/*///]");
        operators = userinput.split("\\d+");
    }   

    //This function will check the input and return true if the user enters a correct expression.
    public boolean checkInput(){
        boolean show = userinput.matches("[-+/*0-9]+");
        return show;
    }

    //This function will add any numbers in the string to the calcOperand array.
    //and any operators to the calcOperator field.
    public void parseInput(String[] item){
        for (String op : item){
            if (op.matches("\\d+")){
                calcOperand.add(Integer.parseInt(op));
            }
            //operators go into calcOperators.
            else if (op.equals("+")||op.equals("-")||op.equals("*")||op.equals("/")){
                calcOperator.add(op);
            }
            else{//everything else is ignored and left. 
            }
        }
    }

    //Function to calculate the priority of each operator.
    //For example * and / will be 1, and + and - will be 2.
    public void calculatePriority(){
        priorityList = calcOperator.toArray(new String[calcOperator.size()]);
        for (int i = 0; i<priorityList.length; i++){
            if (priorityList[i].equals("+")){
                priorityList[i] = "2";
            }else if (priorityList[i].equals("-")) {
                    priorityList[i] = "2";
            }else if (priorityList[i].equals("/")){
                priorityList[i] = "1";
            }else if (priorityList[i].equals("*")){
                priorityList[i] = "1";
            }else{
                System.out.println("error");
            }
        }
    }
    public void printPri(){

        for (String s : priorityList)
            System.out.print(s +",");
    }

    //Function to show the result of the expression.
    public void calculateResult(){
        if(checkInput()){
            parseInput(integers);
            parseInput(operators);
            System.out.println("Operands: " + calcOperand);
            System.out.println("Operators: " + calcOperator);
            calculatePriority();
            System.out.print("Priority: ");
            printPri();
        }else{
            System.out.println("Please enter a valid input!");

        }
    }

}

3 个答案:

答案 0 :(得分:1)

执行此操作的正确方法是将输入解析为AST(抽象语法树)。然后以正确的顺序对表达式进行评估。

试图将所有问题都减少到表格解决方案的倾向是一种巨大的反模式,遗憾的是,许多程序员从未学习过。不是一切都是一张桌子。那里也有树木和图表。

几乎所有解析作业都应该导致树的构造(可能是也可能不是复合模式的实现)。

答案 1 :(得分:1)

生成操作树的一种方法的一个非常基本的例子。

我已经在一个Test类中嵌套了这些类(因为我不想用额外的文件来处理)但是它应该很简单,可以拆分)。

  • MathNode是表示树中节点的抽象类;
  • ElementNodeMathNode的子类,表示数字值(以及树的叶子);
  • SumNode是表示操作的MathNode的子类;
  • tokenize()遍历字符串查找操作(或字符串的结尾)和前面的数字,并创建相应的标记并将它们附加到数组中。
  • makeTree()遍历标记数组,当找到当前正在搜索的操作时,将树的左右节点设置为前一个和后一个标记(一旦添加,就从数组中删除这些标记)到了树)。
  • 运行tokenize()然后makeTree()四次,每次/*-+操作一次,使用标记数组中剩下的单个节点构建树,树是树的根。

可以包含更多错误检查,并且我确信树构建可以显着提高效率(并且不需要四次通过),但是,希望这可以让您了解如何继续。< / p>

代码:

import java.util.ArrayList;

public class Test
{
    public static enum Operation { MULTIPLY, DIVIDE, ADD, SUBTRACT };
    abstract static class MathNode {
        public abstract double calc();
        public abstract String toString();
        public abstract boolean set( final MathNode left, final MathNode right, final Operation op );
    }
    static class ElementNode extends MathNode {
        private final double value;
        public ElementNode( final double v ) {
            this.value = v;
        }
        public double calc() {
            return value;
        }
        public String toString() {
            return Double.toString( value );
        }
        public boolean set( final MathNode left, final MathNode right, final Operation op ){
            return false;
        }
    }
    static class SumNode extends MathNode {
        public MathNode left = null;
        public MathNode right = null;
        public final Operation op;
        public SumNode( final Operation op ){
            this.op = op;
        }
        public boolean set( final MathNode left, final MathNode right, final Operation op ){
            if ( this.op == op )
            {
                this.left = left;
                this.right = right;
                return true;
            }
            return false;
        }
        public double calc() {
            final double l = left  == null ? 0 : left.calc();
            final double r = right == null ? 0 : right.calc();
            switch ( this.op ){
            case MULTIPLY:  return l * r;
            case DIVIDE:    return l / r;
            case SUBTRACT:  return l - r;
            default:        return l + r;
            }
        }
        public String toString(){
            final String l = left  == null?"0":left.toString();
            final String r = right == null?"0":right.toString();
            switch ( this.op ){
            case MULTIPLY:  return "( " + l + " * " + r + " )";
            case DIVIDE:    return "( " + l + " / " + r + " )";
            case SUBTRACT:  return "( " + l + " - " + r + " )";
            default:        return "( " + l + " + " + r + " )";
            }
        }
    }
    public static ArrayList<MathNode> tokenize( final String sum )
    {
        int i = 0,
            p = 0;
        final int l = sum.length();
        final ArrayList<MathNode> tokens = new ArrayList<MathNode>();
        while ( i < l )
        {
            final SumNode sn;
            switch ( sum.charAt(i) ){
            case '*':   sn = new SumNode( Operation.MULTIPLY ); break;
            case '/':   sn = new SumNode( Operation.DIVIDE );       break;
            case '+':   sn = new SumNode( Operation.ADD );      break;
            case '-':   sn = new SumNode( Operation.SUBTRACT ); break;
            default:
                // TODO: Add something to check if number is valid
                ++i; 
                continue;
            }
            // TODO: Add something to check for zero-width numbers 
            final double value = Double.parseDouble( sum.substring( p, i ) );
            p = ++i;
            tokens.add( new ElementNode( value ) );
            tokens.add( sn );
        }
        // TODO: Add something to check for zero-width numbers
        final double value = Double.parseDouble( sum.substring( p ) );
        tokens.add( new ElementNode( value ) );
        return tokens;
    }
    public static void makeTree( final ArrayList<MathNode> tokens, final Operation op ){
        for ( int i = tokens.size() - 2; i >= 1; --i )
        {
            final MathNode node = tokens.get( i );
            if ( node.set( tokens.get(i-1), tokens.get(i+1), op) )
            {
                tokens.remove( i + 1 );
                tokens.remove( i - 1 );
                --i;
            }
        }
    }
    public static void main(final String[] args) {
        final String sum = "23.2-5.2*4.4/2.2+14";
        final ArrayList<MathNode> tokens = tokenize( sum );
        makeTree( tokens, Operation.DIVIDE );
        makeTree( tokens, Operation.MULTIPLY );
        makeTree( tokens, Operation.SUBTRACT );
        makeTree( tokens, Operation.ADD );
        final MathNode sum_tree = tokens.get(0);
        System.out.println( sum_tree + " = " + sum_tree.calc() );
    }
}

答案 2 :(得分:0)

您真的需要扫描所有操作员,计算优先级并重新排序所有内容吗?

如果您浏览了所有运算符和值,并仅评估*/

,该怎么办?

然后重新浏览并评估+-

可能比你想做的容易得多。