Решение простых строковых выражений (1+2*3) в Java [Почти готово]

Я пытаюсь решить простые строковые выражения, например, 1+2*3/4, без скобок. Я закончил с простой целочисленной частью, вышеупомянутое выражение будет работать отлично, но теперь я застрял с десятичными значениями, например 1.1/2.2*4.4 Все, что я хочу, это поместить все десятичное число в стек (double), я Я работаю над этим в течение достаточно долгого времени, но не совсем понимаю, ваша помощь будет высоко ценится. Текущий код:

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

В той части, где значения помещаются в стек "значения", произойдут некоторые изменения.

2 ответа

Решение

Ты сделал! Просто еще немного изменений:

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

Необходимо заменить на

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

Зачем кодировать это самостоятельно? Есть много альтернативных вариантов:

Другие вопросы по тегам