评估多个表达式以确定php中数字变量的范围

时间:2011-01-04 14:26:00

标签: php algorithm

很抱歉,如果标题令人困惑。

我在数组中有几个字符串表达式,如下所示:

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

我理解,对于不是“或等于”的表达式,我将无法获得确切的值。没关系。

5 个答案:

答案 0 :(得分:3)

您正在尝试进行简单的线性编程。 SimplexInPHP在PHP中实现线性编程,您可以使用它。在行动here中查看。

另一种选择是自己实施解决方案。使用split()将每个不等式拆分为令牌。对于每个变量,通过从[-inf,inf]范围开始计算最小值/最大值,并为每个不等式更新它。如果运算符以<开头,则将max更新为max(cur_max, value);否则将min更新为min(cur_min, value)

您还必须跟踪终点是包含还是排他。这可以使用布尔值is_min_inclusiveis_max_inclusive来完成。如果操作员以=结束,则新的终点是包含的,否则它是独占的。请务必处理x < 1 x <= 1(两个订单中)的情况,这应该会导致x < 1

答案 1 :(得分: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);

?>

答案 2 :(得分:1)

因此,在您的示例中,您希望最小var1为> 4.5,最大值为&lt; = 6?您是否考虑过更改数据结构?

例如,如果您的数据结构如下所示:

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

然后解析变得微不足道。 gt和gte数组的最大值将是最小值,使用&gt;或&gt; =取决于它来自哪个阵列。 lt和lte数组的最小值将是最大值。

答案 3 :(得分: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";
?>

答案 4 :(得分:-1)

我猜......

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

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

在示例中,它们显示了数字字符串表达式(因此不仅仅是铸造的浮点数或整数)