• PHP工资计算之逆波兰式


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

    假设有一个计算公式如下:      $expression = "(F1*F12+10.34)";

    其中的变量值如下:

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

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


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

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

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

        function _stringToArray () {
            $temp_operator = null;
            $temp_value = null;

            $this->_input = str_replace(" ","",$this->_input);

            for($i = 0; $i < strlen($this->_input); $i++) {
                if ($this->_input[$i] == ' ') {
                    if ($temp_operator != null) {
                        array_push($this->_input_array, $temp_operator);
                        $temp_operator = null;
                    }
                    if ($temp_value != null) {
                        array_push($this->_input_array, $temp_value);
                        $temp_value = null;
                    }
                } elseif (($temp_value == null) && $temp_operator != ')' && (!array_key_exists($temp_operator,$this->_operation) || !array_key_exists(2,$this->_operation[$temp_operator]) || $this->_operation[$temp_operator][2]>0) && ($this->_input[$i] == '-')) {
                    if ($temp_operator != null) {
                        array_push($this->_input_array, $temp_operator);
                        $temp_operator = null;
                    }

                    array_push($this->_input_array, '-1');
                    array_push($this->_input_array, '*');
                //} elseif ((is_numeric($this->_input[$i])) || ($this->_input[$i] == '.')) {
                } elseif ((is_numeric($this->_input[$i])) || ($this->_input[$i] == '.') || ($this->_input[$i] == 'F')) {
                    if ($temp_operator != null) {
                        array_push($this->_input_array, $temp_operator);
                        $temp_operator = null;
                    }

                    $temp_value .= $this->_input[$i];
                } else {
                    if ($this->_keyExists($temp_operator, $this->_operation, 1)) {
                        array_push($this->_input_array, $temp_operator);
                        $temp_operator = null;
                    }

                    if ($temp_value != null) {
                        array_push($this->_input_array, $temp_value);
                        $temp_value = null;
                    }

                    $temp_operator .= $this->_input[$i];
                }
            }

            if ($temp_operator != null && $temp_operator != ' ') {
                array_push($this->_input_array, $temp_operator);
            } elseif($temp_value != null && $temp_value != ' ') {
                array_push($this->_input_array, $temp_value);
            }

           // $this->_testInput();
    print_r($this->_expression_value);
            print_r($this->_input_array);
            return $this->_input_array;
        }

        function _arrayToRpn() {

            if ($this->_error <> null) {
                $this->_output = array();
                return $this->_output;
            }

            for($i = 0; $i < count($this->_input_array); $i++) {

                $temp = $this->_input_array[$i];
                
                if (is_numeric($temp)) {
                    $this->_outputAdd($temp);
                } else if($this->_keyExists($temp, $this->_expression_value, 0)) {
                   $this->_outputAdd($this->_expression_value[$temp]);
                } else {
                    if ($temp == ')') {
                        while(!$this->_stackEmpty() && ($this->_stackPriority() >= 1)) {
                            $this->_outputAdd($this->_stackDelete());
                        }
                        if (!$this->_stackEmpty()) {
                            $this->_stackDelete();
                        }

                    } elseif ($temp=='(') {
                        $this->_stackAdd($temp);
                    } elseif (($this->_stackEmpty()) || (($this->_priority($temp) > $this->_stackPriority()))) {
                       $this-> _stackAdd($temp);
                    } else {
                        while(!$this->_stackEmpty() && ($this->_priority($temp) <= $this->_stackPriority())) {
                            $this->_outputAdd($this->_stackDelete());
                        }
                        $this->_stackAdd($temp);
                    }

                }

            }

            while(!$this->_stackEmpty()) {
                $this->_outputAdd($this->_stackDelete());
            }

            return $this->_output;
        }

        function _rpnToValue() {

            $time1 = $this->_getMicroTime();

            if ($this->_error <> null) {
                $this->_value = null;
                return $this->_value;
            }

            $this->_value = 0;
            $temp = $this->_output;

            do {
                $pos = $this->_nextOperator($temp);

                if ($pos == -1) {
                    $this->_error = $this->_raiseError('Syntax error');
                    $this->_value = null;
                    return $this->_value;
                }

                $operator = $this->_operation[$temp[$pos]];
                $arg = $operator[2];
                $function = $operator[3];

                if (($arg==2) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]) || !isset($temp[$pos-2]) || !is_numeric($temp[$pos-2]))) {
                    $this->_error = $this->_raiseError('Syntax error');
                    $this->_value = null;
                    return $this->_value;
                } elseif (($arg==1) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]))) {
                    $this->_error = $this->_raiseError('Syntax error');
                    $this->_value = null;
                    return $this->_value;
                }

                if(is_array($function)) {

                    if($arg==2) $arg_array = array($temp[$pos-2],$temp[$pos-1]);
                    elseif($arg==1) $arg_array = array($temp[$pos-1]);
                    else $arg_array = array();

                    if($function['type'] == 'userFunction') {
                        $this->_value = call_user_func_array($function['function'], $arg_array);
                    } else {
                        $function_array = array(&$function['class'], $function['method']);
                        $this->_value = call_user_func_array($function_array, $arg_array);
                    }
                } else {
                    $this->_value = $this->$function($temp, $pos);
                }

                if ($this->_isNan($this->_value)) {
                    $this->_error = $this->_raiseError('NAN value');
                    $this->_value = null;
                    return $this->_value;
                } elseif ($this->_isInfinite($this->_value)) {
                    $this->_error = $this->_raiseError('Infinite value');
                    $this->_value = null;
                    return $this->_value;
                } elseif (is_null($this->_value)) {
                    return $this->_value;
                }

                $temp = $this->_refresh($temp, $pos, $arg, $this->_value);
            } while(count($temp) > 1);

            $this->_value = $temp[0];

            $time2 = $this->_getMicroTime();

            $this->_timer = $time2 - $time1;

            return $this->_value;
        }

  • 相关阅读:
    浅谈Java Future
    图解java泛型的协变和逆变
    编写junit单元测试
    VBA中的Declare PtrSafe兼容64位系统
    在Python反编译中出现Magic value mismatch
    在Python反编译中批量pyc转 py
    ArcGIS Earth数据加载
    ArcGIS Earth 3D交互测量
    Linux系统清空或删除大文件内容5种方法
    安卓模拟器
  • 原文地址:https://www.cnblogs.com/kelite/p/2923040.html
Copyright © 2020-2023  润新知