0

I am having a problem where when I am trying to calculate a scientific expression, it compiles however, it crashes when I run it. The way my program works is that it receives a string containing a mathematical expression which needs to be evaluated. Firstly, it is split into an ArrayList containing numbers and operators separately. It is then searched for any brackets which allows the program to work with the expressions within the brackets first. Then it calls calculate which calculates the answer. The error I keep receiving however is " Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsExcepton: Index:0, Size:0" I assume it has something to do with my sizes of the arraylist however, I cannot spot the error, can anyone else help me figure it out please? I believe the issue is most likely with the methods splitLabel and calculate

public ArrayList<String> splitLabel(String val){
    ArrayList<String> label_split = new ArrayList<String>();
    String value = "";
    String op = "";

    for (int i = 0; i< val.length(); i++){
        boolean isDigit = Character.toString(val.charAt(i)).matches("[0123456789.]+");
        boolean isOperator = Character.toString(val.charAt(i)).matches("[+*/^-]+");
        boolean isSin = (Character.toString(val.charAt(i)).equals("s") && Character.toString(val.charAt(i+1)).equals("i") && Character.toString(val.charAt(i+2)).equals("n"));
        boolean isCos = (Character.toString(val.charAt(i)).equals("c") && Character.toString(val.charAt(i+1)).equals("o") && Character.toString(val.charAt(i+2)).equals("s"));
        boolean isTan = (Character.toString(val.charAt(i)).equals("t") && Character.toString(val.charAt(i+1)).equals("a") && Character.toString(val.charAt(i+2)).equals("n"));
        boolean isOpBracket = Character.toString(val.charAt(i)).equals("(");
        boolean isClBracket = Character.toString(val.charAt(i)).equals(")");  

            if (isOperator && !value.equals("")){
                op = Character.toString(val.charAt(i));
                label_split.add(value);
                label_split.add(op);
                op = "";
                value = "";
            } else if (isOperator && value.equals("")){
                if (Character.toString(val.charAt(i)).equals("-")){
                    value = Character.toString(val.charAt(i));
                }
            } else if (isSin){
                label_split.add("sin");
            }else if (isCos){
                label_split.add("cos");
            }else if (isTan){
                label_split.add("tan");
            } else if (isOpBracket && !value.equals("")){
                label_split.add(value);
                label_split.add("(");
                value = "";
            } else if (isOpBracket && value.equals("")){
                label_split.add("(");
            } else if (isClBracket && !value.equals("")){
                label_split.add(value);
                label_split.add(")");
                value = "";
            }
        if (i== val.length()-1 && !value.equals("")){
            label_split.add(value);
        } else if (i== val.length()-1 && Character.toString(val.charAt(i)).equals(")")){
            label_split.add(")");
        }
    } return label_split;
}   
public String bracket(ArrayList<String> label_split){
    ArrayList<Integer> opBra = new ArrayList<Integer>();
    ArrayList<Integer> clBra = new ArrayList<Integer>();
    ArrayList<String> calculation = new ArrayList<String>();
    int counter = 0;
    int counter1 = 0;

    if (label_split.contains("(") && label_split.contains(")")){
        for (int j=0; j<label_split.size(); j++){
            if (label_split.get(j).equals("(")){
                counter = counter + 1;
                opBra.add(j);
            } else if (label_split.get(j).equals(")")){
                counter1 = counter1 + 1;
                clBra.add(j);
            }
        } 
        if (counter1 != counter){
            return "error missing bracket";
        } else {
            for (int j=opBra.size(); j>0; j--){
                int opBraPos = opBra.get(j) + 1; //+1 and -1 so it doesn't include ()
                int clBraPos = clBra.get(opBra.size()-j) - 1;
                opBra.remove(j);
                clBra.remove(opBra.size()-j);

                for(int t = 0; t < (clBraPos - opBraPos); t++){
                    calculation.add(label_split.get(t+opBraPos));
                }

                String value = calculate(calculation);
                label_split.set(j , value);
                calculation.clear();

                for (int n = 0; n < ((clBraPos+1) - opBraPos); n++){
                    label_split.remove(n);
                }
            }
        }
        return calculate(label_split);
    } else{
        return calculate(label_split);
    } 
}
public String calculate(ArrayList<String> calculation){
    double value = 0.0;
    String value1 = "";
    boolean isOperator = calculation.contains("[+*/^-]+");  
    boolean isSin =  calculation.contains("sin"); //...ETC


    for (int i=0; i < calculation.size(); i++){
        if (calculation.get(i).equals("^") && i < calculation.size() && i < 0){
            boolean isDigit1 = calculation.get(i-1).matches("[0123456789.-]+");
            boolean isDigit2 = calculation.get(i+1).matches("[0123456789.-]+");
            if (isDigit1 && isDigit2){
                value = Math.pow(Double.parseDouble(calculation.get(i-1)), Double.parseDouble(calculation.get(i+1)));
                value1 = Double.toString(value);
                calculation.set(i,value1);
                calculation.remove(i-1);
                calculation.remove(i+1);
            }
        }
    }

    for (int a=0; a < calculation.size(); a++){
        if ( (calculation.get(a)).equals("sin") && a < calculation.size() && a < 0){
            boolean isDigit1 = calculation.get(a+1).matches("[0123456789.-]+");
            if (isDigit1){
                value = Math.sin(Double.parseDouble(calculation.get(a+1)));
                value1 = Double.toString(value);
                calculation.set(a,value1);
                calculation.remove(a+1);
            }
        }
    }

    for (int b=0; b < calculation.size(); b++){
        if ( (calculation.get(b)).equals("cos") && b < calculation.size() && b < 0){
            boolean isDigit1 = calculation.get(b+1).matches("[0123456789.-]+");
            if (isDigit1){
                value = Math.cos(Double.parseDouble(calculation.get(b+1)));
                value1 = Double.toString(value);
                calculation.set(b,value1);
                calculation.remove(b+1);
            }
        }
    } // ETC

    return calculation.get(0);
}
assassinweed2
  • 71
  • 1
  • 3
  • 9
  • Maybe say what line it fails on? – Iluvatar Dec 05 '16 at 10:21
  • It says: "at CalculatorFrameA.calculate(java:578)" which is the final "}" "at CalculatorFrameA.bracket(java:449)" which is "return calculate(label_split);" – assassinweed2 Dec 05 '16 at 10:25
  • To be honest, your code is quite convoluted. Clearly, `calculation` has size 0 by the return, so either it's being passed in as such, or all the elements are being removed. I will say that you remove elements from it while iterating though it and don't adjust `i`, so that alone will give you issues later on. You might take a look at http://stackoverflow.com/questions/114586/smart-design-of-a-math-parser for some better ways to implement a parser. – Iluvatar Dec 05 '16 at 10:47
  • @Iluvatar yup my code is removing each calculation it completes until you are left with one final answer which is then returned... I only have around 2 hours left before my deadline so I don't really have time to create a new method... Do you think my code can still be saved with a few tweaks? – assassinweed2 Dec 05 '16 at 11:03

1 Answers1

0

This is not your problem, but it certainly seems wrong:

calculation.set(i,value1);
calculation.remove(i-1);
calculation.remove(i+1);

The problem is that remove(i-1) is going to cause the index of everything from i onwards to be decremented by one. Then remove(i+1) is going to remove the element that was previously at index i+2.

Then there is this:

for (int i=0; i < calculation.size(); i++){
    if (calculation.get(i).equals("^") && 
        i < calculation.size() && 
        i < 0) {

Think about it. If i starts at zero and is incremented up to size() which is non-negative, how can i ever be less than zero. And if i is never less than zero, how can the if test ever succeed. (You repeat this pattern in other places.)

However, the real problem is that somehow you are calling calculate on an empty list.

I think it is time that you learned to use a debugger .....

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216