2

I'm trying to solve simple string expressions e.g. 1+2*3/4, without brackets. I'm done with simple integer part, the above expression will work perfectly, but now i'm stuck with decimal values, for example 1.1/2.2*4.4 All i want is to push the whole decimal number into stack (double), i'm working on it for quite some time but not quite getting it, your help would be much appreciated. Current code is:

import java.util.Stack;
import java.text.DecimalFormat;

public class EvaluateString
{
    public static double evaluate(String expression)
    {
        char[] tokens = expression.toCharArray();
        DecimalFormat df = new DecimalFormat("#.##");

         // Stack for numbers: 'values'
        Stack<Double> values = new Stack<Double>();

        // Stack for Operators: 'ops'
        Stack<Character> ops = new Stack<Character>();

        for (int i = 0; i < tokens.length; i++)
        {
             // Current token is a whitespace, skip it
            if (tokens[i] == ' ')
                continue;

            // Current token is a number, push it to stack for numbers
            if (tokens[i] >= '0' && tokens[i] <= '9')
            {
                StringBuffer sbuf = new StringBuffer();
                // There may be more than one digits in number
                while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
                    sbuf.append(tokens[i++]);
                values.push(Double.parseDouble(sbuf.toString()));
            }

            // Current token is an operator.
            else if (tokens[i] == '+' || tokens[i] == '-' ||
                     tokens[i] == '*' || tokens[i] == '/')
            {
                // While top of 'ops' has same or greater precedence to current
                // token, which is an operator. Apply operator on top of 'ops'
                // to top two elements in values stack
                while (!ops.empty() && hasPrecedence(tokens[i], ops.peek()))
                  values.push(applyOp(ops.pop(), values.pop(), values.pop()));

                // Push current token to 'ops'.
                ops.push(tokens[i]);
            }
        }

        // Entire expression has been parsed at this point, apply remaining
        // ops to remaining values
        while (!ops.empty())
            values.push(applyOp(ops.pop(), values.pop(), values.pop()));

        // Top of 'values' contains result, return it
        return Double.parseDouble(df.format(Double.parseDouble(String.valueOf(values.pop()))));
    }

    // Returns true if 'op2' has higher or same precedence as 'op1',
    // otherwise returns false.
    public static boolean hasPrecedence(char op1, char op2)
    {
        if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
            return false;
        else
            return true;
    }

    // A utility method to apply an operator 'op' on operands 'a' 
    // and 'b'. Return the result.
    public static double applyOp(char op, double b, double a)
    {
        switch (op)
        {
        case '+':
            return a + b;
        case '-':
            return a - b;
        case '*':
            return a * b;
        case '/':
            if (b == 0)
                throw new
                UnsupportedOperationException("Cannot divide by zero");
            return a / b;
        }
        return 0;
    }
}

There is going to be some change in the part where the values are getting pushed in the 'value' stack.

Abdul Jabbar
  • 2,573
  • 5
  • 23
  • 43

2 Answers2

5

Why code it yourself? There are many thirdtpaty alternatives:

R. Oosterholt
  • 7,720
  • 2
  • 53
  • 77
  • My professors claimed that every real programmer has to write advanced calculator (or programming language) at least once in his life. That is why I am not real programmer :( – Pshemo Jan 31 '14 at 16:16
  • @Pshemo That is why you are not a real programmer in your professors eyes, that's all. Using a library for this is definitely the sanest suggestion. – kritzikratzi Jan 31 '14 at 16:21
  • 1
    I am kidding, I actually have written calculator some time ago and it was great exercise. But I agree that being programmer nowadays is more about finding and learning to correctly use libraries rather than creating them. That is why +1 – Pshemo Jan 31 '14 at 16:33
1

You have done ! Just more little change:

        while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')

Needs to be replaced with

       while (i < tokens.length && (Character.isDigit(tokens[i]) || tokens[i] == '.'))