公式验证算法

    public function test() {
// $str = 'if({who}+{her}>3,if({who}+{her}>3,{her},{her}+{abc}),{her}+{abc})+{her}-({abc}-{her})*{abc}';
$param = $this->param;
$str = $param['str'];
// $str = "if(if({who}+{her}>{abc},{who},{whe})>=if({who}+{her}>3,{her}+5,{her}+{abc}),5,if({her}>3,2,1))+if({who}+{her}>3,if({who}+{her}>3,{her},{her}+{abc}),{her}+{abc})+{her}-({abc}-{her})*{abc}";
//剔除空白符
$str = str_replace(' ', '', $str);
// 错误情况,空字符串
if ("" === $str) {
return false;
}
//判断连续两个因子
if(substr_count($str,'}{')) {
return $this->resultError('不能将两个计算因子写在一起');
}
//判断是否所有因子都在因子集合范围内(替换后,查看是否还存在{)
foreach ($this->items as $v){
$items[] = $v['name'];
}
preg_match_all('/\{.*?\}/',$str,$out);
for ($i = 0; $i < count($out[0]); $i++) {
$item = $out[0][$i];
if (!in_array($item,$items)) {
return $this->resultError('计算因子不合法');
}
}
//判断连续)(
if(substr_count($str,')(')) {
return $this->resultError('不能将两个计算因子写在一起');
}
//判断{}是否成对
$stack = [];
for ($i = 0; $i < strlen($str); $i++) {
$item = $str[$i];
if ('{' === $item) {
array_push($stack,'(');
} elseif ('}' === $item) {
if (count($stack) > 0) {
array_pop($stack);
} else {
return $this->resultError('计算因子不合法');
}
}
}
if (0 !== count($stack)) {
return $this->resultError('计算因子不合法');
}
//判断()是否成对
$stack = [];
for ($i = 0; $i < strlen($str); $i++) {
$item = $str[$i];
if ('(' === $item) {
array_push($stack,'(');
} elseif (')' === $item) {
if (count($stack) > 0) {
array_pop($stack);
} else {
return $this->resultError('括号不配对');
}
}
}
if (0 !== count($stack)) {
return $this->resultError('括号不配对');
}
//错误情况,运算符结尾
if(preg_match('/[\x\÷\+\-\*\/]$/',$str)){
return $this->resultError('不能以运算符结尾');
}
// 错误情况,( 后面是运算符
if(preg_match('/\([\x\÷\*\/]/',$str)){
return $this->resultError('左括号后面不能是运算符');
}
// 错误情况,)前面是运算符
if(preg_match('/[\x\÷\+\-\*\/]\)/',$str)){
return $this->resultError('右括号前面不能是运算符');
}
// 错误情况,运算符连续
if(preg_match('/[\x\÷\+\-\*\/]{2,}/',$str)){
return $this->resultError('运算符不能连续');
}
//空括号
if(substr_count($str,'()')){
return $this->resultError('括号中不能没有内容');
}
// 替换因子为随机的0.1-10
foreach ($items as &$v){
$str = str_replace($v,mt_rand(1,100)/10,$str);
}

// $str = 'if(4.7+2.1>3,if(4.7+2.1>3,2.1,2.1+6.2),2.1+6.2)+2.1-(6.2-2.1)*6.2';
// $str = '5+if(3>2,if(5>4,4,if(9<6,5,6)),1)+2';
$str = $this->getIf($str);
$str = $this->why($str);
$value = $this->cal($str);
if(!$value){
return $this->resultError('公式格式不正确');
}
if($value) {
return $this->resultSucess($value);
}
else
return $this->resultError($value);

}
public function why($str)
{
if(stripos($str,'if(') === false){
return $str;
}
$str = substr($str,3,strlen($str)-4);
$str = $this->getIf($str);
return $this->why($str);
}

//递归把最里层的if算出结果
private function getIf($str)
{
//获取if(第一次出现的位置
$index = stripos($str,'if(');
if($index === false){
$subArr = explode(',',$str);
preg_match('/(\<\=)|(\>\=)|(\!\=)|(\=)|(\<)|(\>)|(\&\&)|(\|\|)/',$subArr[0],$sign);
if(empty($sign)){
return $str;
}
$gt = explode($sign[0],$subArr[0]);
if($sign[0] == '>')
$str = "if(gt({$gt[0]},{$gt[1]}),{$subArr[1]},{$subArr[2]})";
if($sign[0] == '<')
$str = "if(lt({$gt[0]},{$gt[1]}),{$subArr[1]},{$subArr[2]})";
if($sign[0] == '>=')
$str = "if(egt({$gt[0]},{$gt[1]}),{$subArr[1]},{$subArr[2]})";
if($sign[0] == '<=')
$str = "if(elt({$gt[0]},{$gt[1]}),{$subArr[1]},{$subArr[2]})";
if($sign[0] == '=')
$str = "if(eq({$gt[0]},{$gt[1]}),{$subArr[1]},{$subArr[2]})";
if($sign[0] == '!=')
$str = "if(neq({$gt[0]},{$gt[1]}),{$subArr[1]},{$subArr[2]})";
$value = $this->cal($str);
return $value;
}
$strr = substr($str,$index+3);
//找出if括号中的内容
// echo $strr;die;
$stack = [];
for ($i = 0; $i < strlen($strr); $i++) {
$item = $strr[$i];
if ('(' === $item) {
array_push($stack,'(');
} elseif (')' === $item) {
if (count($stack) > 0) {
array_pop($stack);
} else {
//if右边括号在$strr中出现的位置
break;
}
}
}
$if = substr($strr,0,$i);
return str_replace("if($if)",$this->getIf($if),"if($str)");
//
}

猜你喜欢

转载自www.cnblogs.com/ruoruchujian/p/11693935.html
今日推荐