2011-01-04 7 views
1

タイトルが混乱している場合は、ごめんなさい。複数の式を評価してPHPの数値変数の範囲を調べる

私はこのような配列内のいくつかの文字列表現を持っている:

var1 <= 6 && var1 > 3 
var1 > 2 
var1 > 4.5 

var2 < 22.5 
var2 >= 14.25 
var2 < 16 

どのように判断するために、式のすべてを評価するについて行くことができます:私はある表現でそれを理解

var1 min 
var1 max 
var2 min 
var2 max 

私は正確な価値を得ることができません。大丈夫です。

+0

あなたは、文字列ごとに一つの発現を持っていますか、または1つの文字列は、複数の式が含まれていてもよいですか? –

+0

複数の文字列を使用できます。私は明確にするために元の投稿を更新しました。 – Mike

答えて

1
<?php 

    $arr = array("var1 <= 6", 
    "var1 > 2", 
    "var1 > 4.5", 

    "var2 < 22.5", 
    "var2 >= 14.25", 
    "var2 < 16"); 

    function find_min_max($arr, $variable) { 
     $min = '-inf'; 
     $max = 'inf'; 
     while (list($i, $v) = each($arr)) { 
      list($var, $rel, $value) = preg_split('/\s+/', $v); 
      if ($var != $variable) continue; 
      if ($rel == "<" || $rel == "<=") { 
       if ($value < $max) 
        $max = $value; 
      } 
      else if ($rel == ">" || $rel == ">=") { 
       if ($value > $min) 
        $min = $value; 
      } 
     } 
     return array($min, $max); 
    } 
    list($min, $max) = find_min_max($arr, "var1"); 
    echo "var1 $min - $max \n"; 
    list($min, $max) = find_min_max($arr, "var2"); 
    echo "var3 $min - $max \n"; 
?> 
+0

私はOPの考え方は考えていませんが、これは '<'と '<='を区別しないことに注意する価値があります。 – marcog

+0

OPへのアップデートでは、 '" && "'で要素を別々の要素に分割する必要があります。また、要素がPHPのような任意の式である場合、問題は解決できません。 –

+0

"&&"のみを使用していますので、これが機能します。私はあなたが言及したようにそれらを分割する必要があります。 – Mike

3

あなたは単純な線形計画をしようとしています。 SimplexInPHPはPHPで線形プログラミングを実装しています。アクションhereでそれを見てください。

もう1つの方法は、ソリューションを自分で実装することです。 split()を使用して、各不等式をトークンに分割します。各変数について、範囲[-inf、inf]で開始してmin/maxを計算し、それぞれの不等式に対して更新します。オペレータが<で始まる場合は、maxをmax(cur_max, value)に更新します。それ以外の場合は、分をmin(cur_min, value)に更新します。

また、エンドポイントが包括的か排他的かを把握する必要があります。これはブール値is_min_inclusiveis_max_inclusiveで行うことができます。オペレータが=で終了する場合、新しいエンドポイントが含まれます。それ以外の場合は排他的です。 x < 1x <= 1(どちらの注文も)の場合は、x < 1になるはずです。

+0

1つの変数を持つinequationsに線形プログラミングを適用すると、少し過剰なように思えます:) –

+0

@Nikita私は同意しますが、それは言及する価値があると思いました。 :) – marcog

-1

私はあなたが、あなたの例ではそう

+0

私はあきらめる、私は本当にあなたがしようとしていることを理解していない、コンテキストを考えることができません。 –

1

の例では、彼らはnummeric文字列式(そうキャスト山車やint型だけではなく)を表示

http://php.net/manual/en/function.max.php

http://php.net/manual/en/function.min.php

...推測します最小のvar1が4.5より大きく、最大値が< = 6であることを期待していますか?データ構造の変更を検討しましたか?

例えば、あなたのデータ構造は、このような何かを見て、もし:

$limits=array('lte'=>array(6), 'lt'=>array(),'gte'=>array(),'gt'=>(2,4.5);

、その後の解析は簡単になります。 gtおよびgte配列の最大値は最小値になり、>または> =はどの配列から来たかに依存します。 lt配列とlte配列の最小値は最大値です。

2
<?php 

$string = "var1 <= 6 && var1 > 0 && var2 >= 4 && var2 < 200"; 
//creates an array with the key 'name' and 'min OR 'max' 
function parseExpression($expression){ 
    $parts = preg_split("|()+|", $expression,3,PREG_SPLIT_NO_EMPTY); 

    $result = array('name'=>$parts[0]); 
    switch ($parts[1]){ 
     case '<': 
      $parts[2]-=1; 
      //NO BREAK <x same as <=(x-1) 
     case '<=': 
      $result['max'] = $parts[2]; 
      break; 
     case '>': 
      $parts[2]+=1; 
      //NO BREAK >x same as >=(x+1) 
     case '>=': 
      $result['min'] = $parts[2]; 
      break; 
     default: 
      throw new Exception("format not supported");   
    } 
    return $result; 
} 

$expressions = explode("&&", $string); 
$vars = array(); 
foreach ($expressions as $expression){ 
    $parsed = parseExpression($expression); 
    $name = array_shift($parsed); 
    foreach ($parsed as $key => $value){ 
     if (array_key_exists($key,$vars[$name])){ 
      switch ($key){ 
       case 'min': 
        $vars[$name][$key] = min($vars[$name][$key],$value); 
        break; 
       case 'max': 
        $vars[$name][$key] = max($vars[$name][$key],$value); 
        break; 
       default: 
      } 
      throw new Exception("format not supported"); 
     } 
     else{ 
      $vars[$name][$key] = $value;  
     } 
    } 
} 

var_dump($vars); 

?> 
+0

私は、これが最も制限的な表現を考慮に入れていないことに気付きました。最後のものを使用しています。だから私はこの式を持っている:var1> = 5 && var1> = 2それは期待される5の代わりに2のvar1分を与えるつもりです。 – Mike

+0

さて、あなたはそうではありませんでした;)それを編集します。 –

+0

@今、それは予想通りに動作しています。 –