2015-11-17 23 views
2

我面臨的情況,其中允許用戶定義一些條件語句如下:驗證數學表達式,包括關係運算符

x >= 2 
x < 6 
y >= 2 
y > 2*x 

其中x和y是變量。 Java或Python中是否存在能夠計算每個變量的域範圍的庫(例如[2,6]中的x和[2,12]中的y),然後驗證這些表達式?例如,添加語句

x + y <= 2 

應該會導致錯誤。

最好

+0

Java *或* Python?你正在使用兩種語言? –

+0

你允許哪些操作員?要小心,解析這些表達式很容易變得很難。您可能想使用某種外部程序與Mathematica或Maple進行交互。使用科學圖書館可能適合您的需求(SciPy for python爲例),但這可能需要您從您的部分工作。 – orion78fr

+1

圖書館的建議是題外話 –

回答

0

我想你可以手動做到這一點。 AFAIK,沒有內在的方式來處理不平等。

您可以創建一種方法來處理限制,然後根據您的輸入不等式手動分配這些限制。

這可以創建不等式。您可以操縱多個不等式的限制和方向來創建一個系統,然後使用這些系統來驗證等式。

public class Limit { 
    public double limit;   // limit number 
    public boolean isUpperLimit; // essentially the direction 
    public boolean includes;  // differentiates between <= and < 
    public Limit(double limit, boolean isUpperLimit, boolean includes) { 
     this.limit = limit; 
     this.isUpperLimit = isUpperLimit; 
     this.includes = includes; 
    } 
} 
public class Inequality { 
    public Limit limit; 
    public String variable; 
    public Inequality(String inequality) { // if inequality is 
     String variable = inequality.split(" ")[0]; 
     this.variable = variable; 
     String operator = inequality.split(" ")[1]; 
     Double number = Double.parseDouble(inequality.split(" ")[2]); 
     double limit = number; 
     boolean isUpperLimit, includes; 
     switch(operator) { 
      case ">": 
       isUpperLimit = false; 
       includes = false; 
       break; 
      case ">=": 
       isUpperLimit = false; 
       includes = true; 
       break; 
      case "<": 
       isUpperLimit = true; 
       includes = false; 
       break; 
      case ">=: 
       isUpperLimit = true; 
       includes = true; 
       break; 
     } 
     this.limit = new Limit(limit, isUpperLimit, includes); 
    } 
} 

public class System { 
    public Limit lowerLimit; 
    public Limit upperLimit; 
    public System(Inequality ie1, Inequality ie2) { 
     if(ie1.limit.isUpperLimit == ie2.limit.isUpperLimit) { // if same direction 
      if(ie1.limit.isUpperLimit == true) { 
       this.upperLimit = (ie1.limit.limit >= ie2.limit.limit) ? ie1.limit : ie2.limit; 
      } else { 
       this.upperLimit = (ie2.limit.limit >= ie1.limit.limit) ? ie1.limit : ie2.limit; 
      } 
     } 
    } 
} 

代碼是未經測試

如果你有設置系統,那麼現在你可以使用自己的極限,以確定最後的公式是可以或不可以。

+0

感謝您的回答。我已經開始手動檢查變量的域範圍,但有一種印象是,當表達式變得更復雜時,評估會變得很麻煩。我會再一次考慮這一點。 – labrassbandito

+0

@labrassbandito對不起,代碼是如此漫長和混淆。可能有一種更簡單的方法(請參閱其他答案,但我不知道它是如何工作的),但這是我能想到的最簡單的方法。但我只是一個業餘青少年愛好者,他花時間關閉了HW,以積累那些對編程一般知之甚少並能盡力幫助知識水平有限的人。 –

0

在您的問題中,您是不是正在討論解析文本表達式還是討論允許定義謂詞的庫。

如果您指的是後者,Java 8使得定義謂詞相當容易。謂詞可以表示爲:

List<BiFunction<Integer, Integer, Boolean>> conditionals; 

然後設置爲:

conditionals.add((x, y) -> x >= 2); 
conditionals.add((x, y) -> x < 6); 
conditionals.add((x, y) -> y > 2 * x); 

等。

然後對規定範圍內的測試x和y可能看起來像:

private boolean anyMatch(int xMin, int xMax, int yMin, int yMax) { 
    IntStream.rangeClosed(xMin, xMax).anyMatch(x -> 
     IntStream.rangeClosed(yMin, yMax).anyMatch(y -> 
      conditionals.stream().allMatch(c -> c.apply(x, y)))); 
} 

目前,這是假設兩個變量。如果你想擴展由代表作爲地圖變量的值覆蓋任何數量的它仍然可能與內置類:

List<Function<Map<String, Integer>, Boolean>> conditionals; 
conditionals.add(vars -> vars.get("x") >= 2); 
conditionals.add(vars -> vars.get("y") > 2 * vars.get("x")); 

這種設計可以很容易地使用排除添加謂詞不兼容在給定的範圍內。

如果你想做一些更復雜的事情,保留有關允許的範圍的信息,而無需迭代指定的域,那麼我認爲你需要一個自定義的類。

+0

這看起來很有趣。 BitFunction對我來說是新的。我不確定,如果Java 8將在內部使用。我也必須檢查。 – labrassbandito

+0

@labrassbandito您可以在Java 7中使用相同的方法,但您需要創建接口的匿名實現。然而,考慮到你的評論以上關於必須解析字符串,我的答案對你沒什麼用處。 – sprinter