Home > Backend Development > PHP Tutorial > analytical algorithm

analytical algorithm

WBOY
Release: 2016-07-29 08:55:34
Original
1392 people have browsed it

I wrote a parsing program in php when I had nothing to do these days.

For example: (21*12-23-(21+14-(21-31/3+(14-21*12-14))+54)-21)+21*25-22*26

Then The result of the analysis is: -169.33.

The code is now posted. If there is anything wrong, please fellow programmers point it out.

if(isset($_GET['sizhi'])){
    $sizhi=$_GET['sizhi'];
    if(!checkSizhi($sizhi)){
      echo('算式不合法,检查括号是否配对');
    }else{
     $sizhi=priority($sizhi);
     echo(calculate($sizhi)); 
    }
}
 //检查算式是否合法
function checkSizhi($sizhi){
    $Amatch=array();
    $pattern='/((\d|!)\()|([-\+\*\/]\))|[^-\+\*\/!\d\(\)]/';
    if(preg_match($pattern,$sizhi,$Amatch)>0){
      echo('不合法的元素:');
      print_r($Amatch);
      return false;
    }else{
      $kuohao=0;
      for($i=0,$k=strlen($sizhi);$i<$k;$i++){
         if($sizhi[$i]=="("){
               $kuohao++;
         }
         if($sizhi[$i]==")"){
               $kuohao--;
               if($kuohao<0)return false;
         }
      }
      if($kuohao!=0)return false;
      return true;
    }
}
//获得优先权 处理括号内的内容
function priority($sizhi,$start=0){
   for($i=$start;$i<strlen($sizhi);$i++){
     if($sizhi[$i]=="("){
      //递归深内层括号
      $sizhi=priority($sizhi,$i+1);
     }
     if($sizhi[$i]==")"){
       $str=calculate(trim(substr($sizhi,$start-1,$i-$start+2),"\(\)")); 
       //用计算结果替换括号内的东西
       $sizhi=substr_replace($sizhi,$str,$start-1,$i-$start+2);
       //返回内层替换后的字符串
       return $sizhi;
     } 
   }
   return $sizhi;
}
  //计算结果
function calculate($sizhi){
  //在算式前加上+ 号 以便后面用正则提取
  if($sizhi[0]!="-"){
    $sizhi=&#39;+&#39;.$sizhi;
  }
  //处理阶乘
  //判断阶乘是否合法  因为3的双重阶乘就就已经很大了
  $erropar=&#39;/(\.[0-9]+!+)|!{3,}/&#39;;
  $par=&#39;/[1-9][0-9]*!{1,2}/&#39;;
  if(preg_match($erropar, $sizhi)>0){
     echo("阶乘阶段出问题,请改算式");
     exit();
  }else{
    //替换所有阶乘的部分
   $sizhi=preg_replace_callback($par,function($siz){
          return calculateFactorial($siz[0]);
    } 
      , $sizhi);
  }
  //交换符号与数字并计算  
  return change($sizhi);
}
//计算阶乘
function calculateFactorial($sizhi){
      for ($i=0; $i <strlen($sizhi); $i++) { 
         if($sizhi[$i]==&#39;!&#39;){
            $number=substr($sizhi,0,$i)*1;
            $product=1;
            for($j=1;$j<=$number;$j++){
                 $product*=$j;
            }
            $sizhi=substr_replace($sizhi,$product,0,$i+1);
            //递归处理多重阶乘
            return calculateFactorial($sizhi);
         }
      }
      return $sizhi;
}
function change($sizhi){
    if($sizhi[0]!="-"){
       $sizhi=&#39;+&#39;.$sizhi;
    }
    $array=array();
    //提取单个算式 并保存到数组中 提取结果为:例如 +5-3*8/5 提取结果为:+5 -3 *8 /5
    $par=&#39;/[-\+\/\*]-?(\d\.?)+/&#39;;
    preg_match_all($par, $sizhi, $array);
    return sum($array[0]);
}
//计算只含加减乘除的算式
function sum($ziArry){
   for($i=0;$i<count($ziArry);$i++){
    //先计算乘除 遍历整个算式数组 如果有一个数组前边的符号为乘号或者除号 则与前数想乘除 
    //并把前一个清空,然后清除数组中空的元素
       if($ziArry[$i][0]=="*"||$ziArry[$i][0]=="/"){
           $ziArry[$i]=$ziArry[$i-1][0].calut(substr($ziArry[$i-1],1),substr($ziArry[$i],1),$ziArry[$i][0]);
            $ziArry[$i-1]="";
       }    
    }
    //清除数组中空的元素
   $ziArry=calerNu($ziArry);
   //计算加减
    for($i=0;$i<count($ziArry);$i++){
        if($i==0&&$ziArry[0][0]=="-"){
            $ziArry[1]=&#39;+&#39;.calut($ziArry[0],substr($ziArry[1],1),$ziArry[1][0]);
            $ziArry[0]="+0";
        }else if($i!=0){
         $ziArry[$i]=$ziArry[$i-1][0].calut(substr($ziArry[$i-1],1),substr($ziArry[$i],1),$ziArry[$i][0]);
         $ziArry[$i-1]=""; 
        }      
    }
    //去符号
   $relus=calerNu($ziArry)[0];
   if(($relus[0]==$relus[1]&&$relus[0]==&#39;-&#39;)||($relus[0]==$relus[1]&&$relus[0]==&#39;+&#39;)){
     return substr($relus,2);
   }
   if(($relus[0]==&#39;+&#39;&&$relus[0]==&#39;-&#39;)||($relus[0]==&#39;-&#39;&&$relus[0]==&#39;+&#39;)){
    return &#39;-&#39;.substr($relus,2);
   }
    return substr($relus,1);
}
//清除数组中的空元素
function calerNu($array){
   for($i=0;$i<count($array);$i++){
      if($array[$i]==""){
        for ($k=$i; $k<count($array)-1; $k++) { 
             $array[$k]=$array[$k+1];
          } 
          $last=array_pop($array); 
          return calerNu($array);
      }
   }
   return $array;
}
function calut($numberone,$numbertwo,$fu){
    $number
    $numbertwo=$numbertwo*1;
    switch ($fu) {
      case &#39;-&#39;:
         return $numberone-$numbertwo;
      case &#39;+&#39;:
         return $numberone+$numbertwo;
      case &#39;*&#39;:
        return $numberone*$numbertwo;
      case &#39;/&#39;:
          $str=(string)$numberone/$numbertwo;
          //如果除不尽则保留小数点后两位
          $par=&#39;/-?\d+\.\d{2}/&#39;;
          $array=array();
          if(preg_match($par, $str,$array)>0){
            $str=$array[0];
           }
         return $str;
    }
}
Copy after login

The above has introduced the analysis algorithm of the calculation formula, including the relevant aspects. I hope it will be helpful to friends who are interested in PHP tutorials.

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template