Heim >php教程 >php手册 >PHP逆波兰表达式的算法-工资计算专用

PHP逆波兰表达式的算法-工资计算专用

WBOY
WBOYOriginal
2016-06-13 11:00:48991Durchsuche

有个网友写信给我谈到关于PHP计算工资问题。我以前一篇文章中谈到过一种计算工资的方法,不过是偷巧,利用现有的表达式的工具,现在既然有人想要,我就给出一个逆波兰的算法。

我们的目标是实现如下的计算公式:

假设有一个计算公式如下:

<p>$expression = "(F1*F12+10.34)";</p>

其中的变量值如下:

<p>$expression_value = Array('F1'=>10,'F12'=>20);</p>

我们希望用PHP构建一个类来计算出这个表达式的值。这种应用主要用于web工资管理中,用户可以自定义其工资相公式的情况。

<p>$rpn = new Math_Rpn();<br>$rpn->setExpressionValue($expression_value);  <br>echo $rpn->calculate($expression,'deg',false); // 即为相应的值</p>

解析逆波兰表达式的方法,编译原理中有,就是先把表达式分解成符号数组,然后求逆波兰式,最后根据逆波兰式得到其结果。

我分别把三个函数贴在下面,其实本质我就是对Pear的RPN函数进行了Hack。

<p>function _stringToArray () {<br>$temp_operator = null;<br>$temp_value = null;</p><p>$this->_input = str_replace(" ","",$this->_input);</p><p>for($i = 0; $i _input); $i++) {<br>if ($this->_input[$i] == ' ') {<br>  if ($temp_operator != null) {<br>array_push($this->_input_array, $temp_operator);<br>$temp_operator = null;<br>  }<br>  if ($temp_value != null) {<br>array_push($this->_input_array, $temp_value);<br>$temp_value = null;<br>  }<br>} elseif (($temp_value == null) && $temp_operator != ')' && </p><p>(!array_key_exists($temp_operator,$this->_operation) || </p><p>!array_key_exists(2,$this->_operation[$temp_operator]) || </p><p>$this->_operation[$temp_operator][2]>0) && ($this->_input[$i] == '-')) {<br>  if ($temp_operator != null) {<br>array_push($this->_input_array, $temp_operator);<br>$temp_operator = null;<br>  }</p><p>  array_push($this->_input_array, '-1');<br>  array_push($this->_input_array, '*');<br>//} elseif ((is_numeric($this->_input[$i])) || ($this->_input[$i] == '.')) {<br>} elseif ((is_numeric($this->_input[$i])) || ($this->_input[$i] == '.') || </p><p>($this->_input[$i] == 'F')) {<br>  if ($temp_operator != null) {<br>array_push($this->_input_array, $temp_operator);<br>$temp_operator = null;<br>  }</p><p>  $temp_value .= $this->_input[$i];<br>} else {<br>  if ($this->_keyExists($temp_operator, $this->_operation, 1)) {<br>array_push($this->_input_array, $temp_operator);<br>$temp_operator = null;<br>  }</p><p>  if ($temp_value != null) {<br>array_push($this->_input_array, $temp_value);<br>$temp_value = null;<br>  }</p><p>  $temp_operator .= $this->_input[$i];<br>}<br>}</p><p>if ($temp_operator != null && $temp_operator != ' ') {<br>array_push($this->_input_array, $temp_operator);<br>} elseif($temp_value != null && $temp_value != ' ') {<br>array_push($this->_input_array, $temp_value);<br>}</p><p>// $this->_testInput();<br>print_r($this->_expression_value);<br>print_r($this->_input_array);<br>return $this->_input_array;<br>  }</p><p>  function _arrayToRpn() {</p><p>if ($this->_error  null) {<br>$this->_output = array();<br>return $this->_output;<br>}</p><p>for($i = 0; $i _input_array); $i++) {</p><p>$temp = $this->_input_array[$i];</p><p>if (is_numeric($temp)) {<br>  $this->_outputAdd($temp);<br>} else if($this->_keyExists($temp, $this->_expression_value, 0)) {<br>  $this->_outputAdd($this->_expression_value[$temp]);<br>} else {<br>  if ($temp == ')') {<br>while(!$this->_stackEmpty() && ($this->_stackPriority() >= 1)) {<br>$this->_outputAdd($this->_stackDelete());<br>}<br>if (!$this->_stackEmpty()) {<br>$this->_stackDelete();<br>}</p><p>  } elseif ($temp=='(') {<br>$this->_stackAdd($temp);<br>  } elseif (($this->_stackEmpty()) || (($this->_priority($temp) > </p><p>$this->_stackPriority()))) {<br>$this-> _stackAdd($temp);<br>  } else {<br>while(!$this->_stackEmpty() && ($this->_priority($temp) </p><p>_stackPriority())) {<br>$this->_outputAdd($this->_stackDelete());<br>}<br>$this->_stackAdd($temp);<br>  }</p><p>}</p><p>}</p><p>while(!$this->_stackEmpty()) {<br>$this->_outputAdd($this->_stackDelete());<br>}</p><p>return $this->_output;<br>}</p><p>function _rpnToValue() {</p><p>$time1 = $this->_getMicroTime();</p><p>if ($this->_error  null) {<br>$this->_value = null;<br>return $this->_value;<br>}</p><p>$this->_value = 0;<br>$temp = $this->_output;</p><p>do {<br>$pos = $this->_nextOperator($temp);</p><p>if ($pos == -1) {<br>  $this->_error = $this->_raiseError('Syntax error');<br>  $this->_value = null;<br>  return $this->_value;<br>}</p><p>$operator = $this->_operation[$temp[$pos]];<br>$arg = $operator[2];<br>$function = $operator[3];</p><p>if (($arg==2) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]) || </p><p>!isset($temp[$pos-2]) || !is_numeric($temp[$pos-2]))) {<br>  $this->_error = $this->_raiseError('Syntax error');<br>  $this->_value = null;<br>  return $this->_value;<br>} elseif (($arg==1) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]))) {<br>  $this->_error = $this->_raiseError('Syntax error');<br>  $this->_value = null;<br>  return $this->_value;<br>}</p><p>if(is_array($function)) {</p><p>  if($arg==2) $arg_array = array($temp[$pos-2],$temp[$pos-1]);<br>  elseif($arg==1) $arg_array = array($temp[$pos-1]);<br>  else $arg_array = array();</p><p>  if($function['type'] == 'userFunction') {<br>$this->_value = call_user_func_array($function['function'], $arg_array);<br>  } else {<br>$function_array = array(&$function['class'], $function['method']);<br>$this->_value = call_user_func_array($function_array, $arg_array);<br>  }<br>} else {<br>  $this->_value = $this->$function($temp, $pos);<br>}</p><p>if ($this->_isNan($this->_value)) {<br>  $this->_error = $this->_raiseError('NAN value');<br>  $this->_value = null;<br>  return $this->_value;<br>} elseif ($this->_isInfinite($this->_value)) {<br>  $this->_error = $this->_raiseError('Infinite value');<br>  $this->_value = null;<br>  return $this->_value;<br>} elseif (is_null($this->_value)) {<br>  return $this->_value;<br>}</p><p>$temp = $this->_refresh($temp, $pos, $arg, $this->_value);<br>} while(count($temp) > 1);</p><p>$this->_value = $temp[0];</p><p>$time2 = $this->_getMicroTime();</p><p>$this->_timer = $time2 - $time1;</p><p>return $this->_value;<br>  }</p>
   
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn