【问题标题】:Writing String evaluation function编写字符串求值函数
【发布时间】:2012-07-02 22:43:32
【问题描述】:

我正在尝试编写一个字符串评估函数,即

evaluate("4 + 1") ; // returns 5 
evaluate("4 + 1 + 3") ; // returns 8 
evaluate("4 + 1 * 3") ; // returns 7 (not 15) 

The operators are + - / and *

我最初的想法是使用正则表达式来收集运算符和数字,因为它们可以匹配。而不是在找到该信息之后,以某种方式找出一种方法来优先考虑 /* ove -+ 运营商。

我是这样开始的:

static String regex = "([\\+\\*-/])+";
static String digitRegex = "(\\d)+";

public static void main(String[] args) {
    System.out.println(getOperators("4 + 1 * 3"));
}

public static List<String> getOperators(String input) {
    Pattern p = Pattern.compile(regex);
    Matcher matcher = p.matcher(input);

    List<String> operatorList = new ArrayList<String>();

    int count = 0;
    while (matcher.find()){
        if (matcher.group(count) != null && matcher.group(count).trim().length() > 0) {
        operatorList.add(matcher.group(count));
        count++;
        }
    }

    return operatorList;
}

现在我可以编写另一种方法来使用相同的逻辑提取数字。

public static List<Integer> getDigits(String input) {
        Pattern p = Pattern.compile(digitRegex);
        Matcher matcher = p.matcher(input);

        List<Integer> digitList = new ArrayList<Integer>();

        int count = 0;
        while (matcher.find()) {
            if (matcher.group(count) != null && matcher.group(count).trim().length() > 0) {
                digitList.add(Integer.valueOf(matcher.group(count)));
                count++;
            }
        }

        return digitList;
    }

现在是我卡住的部分。 #1 上述方法在第三个示例中失败:

evaluate("4 + 1 * 3") ; // returns 7 (not 15) 

而这个 #2 即使我尝试前面的示例,我也无法弄清楚如何将它们按正确的顺序排列。

我是不是在正确的轨道上,有没有人有一些有用的建议请分享?

【问题讨论】:

标签: java evaluation operator-precedence expression-evaluation


【解决方案1】:

我在这里写了一些东西......让我们说快速和肮脏是轻描淡写......
无论如何,你不应该“按原样”使用它。它需要“修复”——数字/算术运算的读取应该使用 StringTokenizer 来完成——但我会把技术问题留给你;)

public class NewClass {

    public static int evaluate(String str){
        if("".equals(str)){
            return 0;
        }
        else if(str.length() == 1){
            return Integer.valueOf(str);
        }
        else{
            String _a = String.valueOf(str.charAt(0));
            String _b = String.valueOf(str.charAt(1));
            if("+".equals(_b) || "-".equals(_b) ){
                if("+".equals(_b)){
                    return Integer.valueOf(_a) + evaluate(str.substring(2));
                }
                else{// "-"
                    return Integer.valueOf(_a) - evaluate(str.substring(2));
                }
            }
            else{// "*" or "/"
                boolean isMulti = ("*".equals(_b));
                String  _c = String.valueOf(str.charAt(2));                
                Integer tmp = 0;
                if(isMulti){
                    tmp = Integer.valueOf(_a) * Integer.valueOf(_c);
                }
                else{
                    tmp = Integer.valueOf(_a) / Integer.valueOf(_c);
                }
                String new_str = String.valueOf(tmp) + str.substring(3);                
                return evaluate(new_str);
            }
        }
    }

    public static void main(String[] args){        
        String e = "4+1*3";
        int t = evaluate(e);
        System.out.println(e + " = "+t);
    }

}

【讨论】:

    【解决方案2】:

    你想要一个operator precedence parser。这是一个非常常见的基于表的解析器,旨在完全满足您的需求。基本上,您将正在扫描的运算符与堆栈顶部的运算符进行比较,然后选择减少堆栈(即进行数学运算并将结果压回堆栈),或压入运算符。

    作为额外的好处,OPP 编写起来既简单又有趣。您可以毫不费力地添加对括号等的支持。

    edit - 我刚刚阅读了那篇 wiki 文章。 太可怕了。

    查找此类解析器的其他示例。

    编辑 2 -

    This one shows a sample in c. Note the table.

    This one is pretty good.

    请记住,您只支持少数运营商,所以不要被吓倒。此外,一旦你实现了一个表,一切都是一样的。

    【讨论】:

      猜你喜欢
      • 2015-05-12
      • 1970-01-01
      • 1970-01-01
      • 2017-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-29
      • 2023-02-04
      相关资源
      最近更新 更多