首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >一种高效解析多位算术表达式的方法

一种高效解析多位算术表达式的方法
EN

Stack Overflow用户
提问于 2015-08-17 23:19:40
回答 2查看 99关注 0票数 0

例如,假设我有一个字符串表达式"10.2*(8-6)/3+112.5“

我需要将数字插入到列表中,并将运算符插入到不同的列表中

我目前(丑陋的)方法:

代码语言:javascript
运行
复制
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;


public class Test {



    public static void main (String args[]) 
    {
        String expression = "10.2*(8-6)/3+112.5"; 
        List<Character> firstList = new ArrayList<Character>();
        List<String> secondList = new ArrayList<String>();

         // Temporary string to hold the number
        StringBuilder temp = new StringBuilder();

        for(int i = 0; i != expression.length(); ++i)
        {           
            if(Character.isDigit(expression.charAt(i)))
            {
                /* If we encounter a digit, read all digit next to it and append to temp
                 * until we encounter an operator.
                 */
                temp.append(expression.charAt(i));

                while((i+1) != expression.length() && (Character.isDigit(expression.charAt(i+1)) 
                                                  || expression.charAt(i+1) == '.'))
                {
                    temp.append(expression.charAt(++i));
                }

                // Next token is either an operator or end of expression
                // Put the number into the list and clear temp for next number
                secondList.add(temp.toString());
                temp.delete(0, temp.length());
            }
            // Getting here means the token is an operator
            else
                firstList.add(expression.charAt(i));
        }

        System.out.print("Numbers: ");
        for(String str : secondList)
            System.out.print(str + " ");

        System.out.println();
        System.out.print("Operators: ");
        for(Character ch  : firstList)
            System.out.print(ch.toString() + " ");
    }   
}

测试运行:

代码语言:javascript
运行
复制
Numbers: 10.2 8 6 3 112.5 
Operators: * ( - ) / + 

这在某种程度上是可行的,但我相信有更干净、更有效的方法。提前感谢!

EN

回答 2

Stack Overflow用户

发布于 2015-08-17 23:23:42

我将创建一个包含所有操作的列表,以便稍后进行检查:

代码语言:javascript
运行
复制
List<Character> operations = new ArrayList<Character>();
operations.add('*'); // put all operations * / ( ) etc...

并优化检查十进制数的方式:

代码语言:javascript
运行
复制
while (!operations.contains(expression.charAt(i)) && i < (expression.length()-1)) 
                    i++;     
secondList.add(expression.substring(c, i));

然后,当您从字符串中获取字符时,只需检查:

代码语言:javascript
运行
复制
for(int i = 0; i != expression.length(); ++i) {
    if (operations.contains(expression.charAt(i))) {
        firstList.add(expression.charAt(i));
    } else {
        int c = i;
        while (!operations.contains(expression.charAt(i)) && i < (expression.length()-1)) 
                i++; 

        secondList.add(expression.substring(c, i));
        if (i < (expression.length()-1)) i--;
    }
}

检查working demo here

票数 0
EN

Stack Overflow用户

发布于 2015-08-18 01:58:10

您还可以使用基本正则表达式匹配来分隔要解析的表达式中的操作数和运算符。

下面是一个使用正则表达式[^\*\-\(\)\/\+]+的工作示例。您将找到代码后面使用的正则表达式的详细解释,以及代码背后作为内联注释的思想。

代码语言:javascript
运行
复制
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ArithmeticExpressionParser 
{
    public void parse(String expression, List<Character> operatorList, 
            List<String> operandList)
    {
        // Create a string of (escaped) operators. Just append all other 
        // operators that you may need.
        StringBuffer operators = new StringBuffer();
        operators.append("\\*");  // *
        operators.append("\\-");  // -
        operators.append("\\(");  // (
        operators.append("\\)");  // )
        operators.append("\\/");  // /
        operators.append("\\+");  // +

        // Compile and match a regular expression matching sequences of
        // non-operator characters against the given expression.
        Pattern pattern = Pattern.compile("[^" + operators + "]+");
        Matcher matcher = pattern.matcher(expression);

        // For each matched subsequence (which represents an operand)...
        int previousEnd = 0;
        while(matcher.find()) {

            // ... add all the operator characters between the end of the last
            // match and the beginning of this match to the operator list ...
            for (int i=previousEnd; i<matcher.start(); i++) {
                operatorList.add(expression.charAt(i));
            }

            // ... and the current match to the operand list.
            operandList.add(
                    expression.substring(matcher.start(), matcher.end()));

            previousEnd = matcher.end();
        }
    }
}

正则表达式的解释:方括号只是将一组字符组合在一起,在本例中是所有运算符。“^”表示组应该包含除后面提到的字符之外的所有字符,所以这个组实际上是指“所有非运算符”。后面提到的运算符由\进行转义,因为否则它们将被解释为正则表达式中的特殊字符。最后,对于括号后面的非转义´+´,我们表示希望匹配括号内一个或多个字符的序列。因为我们将正则表达式作为java字符串给出,所以我们实际上需要转义两次,因为\必须在java字符串中进行转义。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32054022

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档