4

我有一个使用 Java 运行的家庭自动化系统,我想添加简单的数学功能,例如加法、减法、乘法、除法、根和幂。

在系统当前状态下,它可以将短语转换为标签,如下例所示:

例子:

Phrase: "what is one hundred twenty two to the power of seven"
Tagged: {QUESTION/math} {NUMBER/122} {MATH/pwr} {NUMBER/7}

例子:

Phrase: "twenty seven plus pi 3 squared"
Tagged: {NUMBER/27} {MATH/add} {NUMBER/3.14159} {MATH/multiply} {MATH/pwr} {NUMBER/2}

这个例子可以很容易地转换成这样的:

27 + 3.14159 * 3^2

每个标签都是一个可以查询其值的对象。

编辑:具体问题:

所以现在我需要一种方法来读取这组标签作为一个方程,并返回一个数值结果。作为最后的手段,我可​​以使用 google 或 wolfram alpha,但这会更慢,而且我试图让自动化系统完全独立。

如果您想查看整个源代码,请访问 github。 请注意,我没有提交最后几个更改,因此我给出的一些与数学相关的示例将不起作用。

4

4 回答 4

3

经过更多的谷歌搜索(我一开始不知道我在做什么),我发现有人已经做了类似的事情:

http://www.objecthunter.net/exp4j/

编辑:完成: https ://github.com/Sprakle/HomeAutomation/blob/master/HomeAutomation/src/net/sprakle/homeAutomation/interpretation/module/modules/math/Math.java

于 2013-04-08T00:02:38.537 回答
1

本,他是对的。采用自然语言的解析动作要困难得多。您需要做的是为表达式添加数学优先级。您这样做的方法是将表达式置于某种预期的形式中,例如 post/pre/in-fix 并提供评估算法(post-fix 最终pop(), pop(), evaluate(), push();为运算符和操作数的交集。这不是您可以快速或轻松完成的任何事情。

于 2013-04-07T23:56:04.820 回答
1

您需要的是一种解析方法,它将建立一个方程式并从您的文本中返回一个答案。我将采取一条线并逐步完成这种方法,然后您需要自己解决。请注意,这只是一个一般性的想法,Java 以外的一些语言可能更适合这种操作。

{QUESTION/math} {NUMBER/122} {MATH/pwr} {NUMBER/7}

//let's assume that the preprocessor reduces the input to an array that is something like this:
// [122, pwr, 7] (this is a very common construction in a language like LISP).

public static int math(string[] question){

   while(i < question.length){
      if(question[i] == "pwr"){
           return pow(Integer.parseInt(question[i-1]), Integer.parseInt(question[i+1]);
       }
       i++;
   }
  return 0;
}

基本上,您需要的是一种从中缀到前缀表示法的好方法,只需一点字符串即可进行任何转换。

这样做可能有比我上面制作的更好的结构,但是这样的东西应该能让你继续前进。

于 2013-04-08T00:05:49.213 回答
0

我写的代码依赖于给定的标签顺序是 "NUMBER" "MATH" "NUMBER" "MATH" "NUMBER" 并且它完全忽略了 math 中的操作规则。它只是您可以做的一个大纲,因此您可能需要对其进行一些修复才能做您想做的事情。

由于时间不够,我没有测试这个文件,所以如果有必要调试它!

import net.sprakle.homeAutomation.interpretation.tagger.tags.*;
import java.util.List;
import java.util.Arrays;

public class Math {

    private Tag[] tags; //Stores the converted tags as a "MathTag"

    //Requires an array of tags
    public Math(Tag[] inputTags) {
        tags = new MathTag[inputTags.length]; //create a new MathTag array
        System.arraycopy(inputTags, 0, tags, 0, tags.length); //Convert Tag array to MathTag array
    }

    //returns a value based on the tags
    //TODO: ADD MATHEMATICAL ORDER OF OPERATIONS!!!
    public double performMath() {
        double value = 0;//initial value to return

        for (int i = 0; i < tags.length; i++) { //perform initial check of the phrase given
            if (tags[i].getType() = TagType.NUMBER && !tags[i].getWasChecked() && i + 1 < tags.length) {
                value = performOperation(i, value, Double.parseDouble(tags[i].getValue()), tags[i+1].getType());
            } else if (tags[i].getType() = TagType.MATH && !tags[i].getWasChecked() && i + 1 < tags.length) {
                value = performOperation(i, value, Double.parseDouble(tags[i + 1].getValue()), tag.getType()); //I'm not positive if this would not cause issues
            }
        }
    }

    //Perform individual operations given the index of the operation, value1, value2, and the operation type
    //The order of the array "operations" must match the order of the operations in the switch statement.
    public double peformOperation(int i, double value1, double value2, String operation) {
        String[] operations = {"add", "subtract", "multiply", "divide", "pwr", "root"}; //Array of operations
        List list = Arrays.asList(operations); //Not exactly effecient, used to check what operation to perform

        switch (list.indexOf(operation)) { //Perform a task based on the operation
            case 0: //Addition
                tags[i].setChecked(true); //Number
                tags[i + 1].setChecked(true); //Operation
                return value1 + value2;
            case 1: //Subtraction
                tags[i].setChecked(true); //Number
                tags[i + 1].setChecked(true); //Operation
                return value1 - value2;
            case 2: //Multiplication
                tags[i].setChecked(true); //Number
                tags[i + 1].setChecked(true); //Operation
                return value1 * value2;
            case 3: //Division
                tags[i].setChecked(true); //Number
                tags[i + 1].setChecked(true); //Operation
                return value1 / value2;
            case 4: //Power
                tags[i].setChecked(true); //Number
                tags[i + 1].setChecked(true); //Operation
                return value1 * value1;
            case 5: //Square Root
                tags[i].setChecked(true); //Number
                tags[i + 1].setChecked(true); //Operation
                return Math.sqrt(value1);
        }

        return error(); //Non-valid operation found
    }

    //Need some way to detect an error
    public double error() {
        return 0;
    }

    //Need some way to check if a tag was looked at before
    class MathTag extends Tag {

        protected static boolean wasChecked = false;

        public void setChecked(boolean checked) {
            wasChecked = true;
        }

        public boolean getWasChecked() {
            return wasChecked;
        }
    }
}
于 2013-04-08T00:47:38.953 回答