zoukankan      html  css  js  c++  java
  • 公式验证算法

        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)");
    //
    }
  • 相关阅读:
    Postman安装出错.NET Framework 4.5 failed to install
    给小白的资源
    windows update自启动解决方法
    Fragment简介及使用
    samba修复
    我的Android知识结构图——20200507停止更新,后续通过标签或分类继续完善结构图
    Android_适配器(adapter)之BaseAdapter
    Android_适配器(adapter)之SimpleAdapter
    Android_适配器(adapter)之ArrayAdapter
    Linux部分场景非常有用的命令集1_chattr&ldd&xargs&screen&ssh&磁盘&du
  • 原文地址:https://www.cnblogs.com/ruoruchujian/p/11693935.html
Copyright © 2011-2022 走看看