解决用Java编写的数学方程式

时间:2015-05-12 00:38:17

标签: java

我试图解决这样的等式:四加十除以(五十五加九)

以便我得到回复: 4.15625

我知道我可以这样解决String sentence = "4+10/(55+9)"的等式:

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String infix = sentence;
try {
    System.out.println(engine.eval(infix));
} catch (ScriptException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

但无论如何只需要解决单词(nine..plus..divide ..)等式。 或者有没有办法将单词(nine..plus..divide ..)转换为像(9 ... + ... / ...)然后使用上面显示的函数来解决它?

谢谢!

1 个答案:

答案 0 :(得分:1)

你可以选择像antlr这样的解析器库,如果你想要一个完整的,富有表现力的语言和正确的错误处理,这可能是更好的主意。

对于快速而肮脏的解决方案,您可以使用正则表达式和替换映射编写自己的解析器:

public class NaturalLanguageMath {

    public static void main(String[] args) {
        String sentence = "Four plus Ten divided by (fifty-five plus nine)";
        System.out.println(toMath(sentence));
    }

    // Regular expression that will match our symbols
    // special case for "divided by" since that's two words for one symbol
    static final Pattern SYMBOL_PATTERN = Pattern.compile("(divided by|[a-z-]+)", Pattern.CASE_INSENSITIVE);

    private static String toMath(String sentence) {
        // Builder to build the translated string
        StringBuilder builder = new StringBuilder();
        // End of the last matched group
        int lastEnd = 0;
        // Go through all symbols in the string
        Matcher matcher = SYMBOL_PATTERN.matcher(sentence);
        while(matcher.find()) {
            // The matched symbol
            String symbol = matcher.group(0).toLowerCase();
            // Get the replacement
            String replacement = getReplacement(symbol);
            // Append everything between the previous match and this match
            builder.append(sentence.substring(lastEnd, matcher.start()));
            // Append the replacement
            builder.append(replacement);
            // Update the end
            lastEnd = matcher.end();
        }
        // Append the end of the string and return it
        builder.append(sentence.substring(lastEnd));
        return builder.toString();
    }

    // Map to hold replacement symbols
    static final HashMap<String, String> REPLACEMENT_MAP = new HashMap<>();
    static {
        REPLACEMENT_MAP.put("four", "4");
        REPLACEMENT_MAP.put("plus", "+");
        REPLACEMENT_MAP.put("ten", "10");
        REPLACEMENT_MAP.put("fifty", "50");
        REPLACEMENT_MAP.put("five", "5");
        REPLACEMENT_MAP.put("nine", "9");
        REPLACEMENT_MAP.put("divided by", "/");
    }

    private static String getReplacement(String symbol) {
        // Handle compounds such as fifty-five
        if(symbol.contains("-")) {
            // add each individual symbol together and return the result
            // this is far from perfect since it will allow compounds such as
            // fifty-five-nine which would become 64
            int value = 0;
            // Go through each individual symbol and translate it
            String[] symbols = symbol.split("-");
            for(String s : symbols) {
                if(!REPLACEMENT_MAP.containsKey(s)) {
                    throw new IllegalArgumentException("Unknown symbol: " + s);
                }
                value += Integer.parseInt(getReplacement(s));
            }
            return String.valueOf(value);
        // Straight translation
        } else if (REPLACEMENT_MAP.containsKey(symbol)) {
            return REPLACEMENT_MAP.get(symbol);
        // Unknown symbol
        } else {
            throw new IllegalArgumentException("Unknown symbol: " + symbol);
        }
    }
}

输出:

  

4 + 10 /(55 + 9)