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='+'.$sizhi; } //处理阶乘 //判断阶乘是否合法 因为3的双重阶乘就就已经很大了 $erropar='/(\.[0-9]+!+)|!{3,}/'; $par='/[1-9][0-9]*!{1,2}/'; 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]=='!'){ $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='+'.$sizhi; } $array=array(); //提取单个算式 并保存到数组中 提取结果为:例如 +5-3*8/5 提取结果为:+5 -3 *8 /5 $par='/[-\+\/\*]-?(\d\.?)+/'; 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]='+'.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]=='-')||($relus[0]==$relus[1]&&$relus[0]=='+')){ return substr($relus,2); } if(($relus[0]=='+'&&$relus[0]=='-')||($relus[0]=='-'&&$relus[0]=='+')){ return '-'.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 '-': return $numberone-$numbertwo; case '+': return $numberone+$numbertwo; case '*': return $numberone*$numbertwo; case '/': $str=(string)$numberone/$numbertwo; //如果除不尽则保留小数点后两位 $par='/-?\d+\.\d{2}/'; $array=array(); if(preg_match($par, $str,$array)>0){ $str=$array[0]; } return $str; } }
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.