1 -工资计算专用
2
3 关于PHP计算工资问题。以下一篇文章中谈到一种计算工资的方法,称作逆波兰的算法。
4
5 我们的目标是实现如下的计算公式:
6
7 假设有一个计算公式如下:
8
9 $expression = "(F1*F12+10.34) ";
10
11 其中的变量值如下:
12
13 $expression_value = Array( 'F1 '=> 10, 'F12 '=> 20);
14
15 我们希望用PHP构建一个类来计算出这个表达式的值。这种应用主要用于web工资管理中,用户可以自定义其工资相公式的情况
16
17 $rpn = new Math_Rpn();
18 $rpn-> setExpressionValue($expression_value);
19 echo $rpn-> calculate($expression, 'deg ',false); // 即为相应的值
20
21 解析逆波兰表达式的方法,编译原理中有,就是先把表达式分解成符号数组,然后求逆波兰式,最后根据逆波兰式得到其结果。
22
23 我分别把三个函数贴在下面,其实本质我就是对Pear的RPN函数进行了Hack.
24
25 function _stringToArray () {
26 $temp_operator = null;
27 $temp_value = null;
28
29 $this-> _input = str_replace( " ", " ",$this-> _input);
30
31 for($i = 0; $i < strlen($this-> _input); $i++) {
32 if ($this-> _input[$i] == ' ') {
33 if ($temp_operator != null) {
34 array_push($this-> _input_array, $temp_operator);
35 $temp_operator = null;
36 }
37 if ($temp_value != null) {
38 array_push($this-> _input_array, $temp_value);
39 $temp_value = null;
40 }
41 } 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] == '- ')) {
42 if ($temp_operator != null) {
43 array_push($this-> _input_array, $temp_operator);
44 $temp_operator = null;
45 }
46
47 array_push($this-> _input_array, '-1 ');
48 array_push($this-> _input_array, '* ');
49 //} elseif ((is_numeric($this-> _input[$i])) || ($this-> _input[$i] == '. ')) {
50 } elseif ((is_numeric($this-> _input[$i])) || ($this-> _input[$i] == '. ') || ($this-> _input[$i] == 'F ')) {
51 if ($temp_operator != null) {
52 array_push($this-> _input_array, $temp_operator);
53 $temp_operator = null;
54 }
55
56 $temp_value .= $this-> _input[$i];
57 } else {
58 if ($this-> _keyExists($temp_operator, $this-> _operation, 1)) {
59 array_push($this-> _input_array, $temp_operator);
60 $temp_operator = null;
61 }
62
63 if ($temp_value != null) {
64 array_push($this-> _input_array, $temp_value);
65 $temp_value = null;
66 }
67
68 $temp_operator .= $this-> _input[$i];
69 }
70 }
71
72 if ($temp_operator != null && $temp_operator != ' ') {
73 array_push($this-> _input_array, $temp_operator);
74 } elseif($temp_value != null && $temp_value != ' ') {
75 array_push($this-> _input_array, $temp_value);
76 }
77
78 // $this-> _testInput();
79 print_r($this-> _expression_value);
80 print_r($this-> _input_array);
81 return $this-> _input_array;
82 }
83
84 function _arrayToRpn() {
85
86 if ($this-> _error <> null) {
87 $this-> _output = array();
88 return $this-> _output;
89 }
90
91 for($i = 0; $i < count($this-> _input_array); $i++) {
92
93 $temp = $this-> _input_array[$i];
94
95 if (is_numeric($temp)) {
96 $this-> _outputAdd($temp);
97 } else if($this-> _keyExists($temp, $this-> _expression_value, 0)) {
98 $this-> _outputAdd($this-> _expression_value[$temp]);
99 } else {
100 if ($temp == ') ') {
101 while(!$this-> _stackEmpty() && ($this-> _stackPriority() > = 1)) {
102 $this-> _outputAdd($this-> _stackDelete());
103 }
104 if (!$this-> _stackEmpty()) {
105 $this-> _stackDelete();
106 }
107
108 } elseif ($temp== '( ') {
109 $this-> _stackAdd($temp);
110 } elseif (($this-> _stackEmpty()) || (($this-> _priority($temp) > $this-> _stackPriority()))) {
111 $this-> _stackAdd($temp);
112 } else {
113 while(!$this-> _stackEmpty() && ($this-> _priority($temp) <= $this-> _stackPriority())) {
114 $this-> _outputAdd($this-> _stackDelete());
115 }
116 $this-> _stackAdd($temp);
117 }
118
119 }
120
121 }
122
123 while(!$this-> _stackEmpty()) {
124 $this-> _outputAdd($this-> _stackDelete());
125 }
126
127 return $this-> _output;
128 }
129
130 function _rpnToValue() {
131
132 $time1 = $this-> _getMicroTime();
133
134 if ($this-> _error <> null) {
135 $this-> _value = null;
136 return $this-> _value;
137 }
138
139 $this-> _value = 0;
140 $temp = $this-> _output;
141
142 do {
143 $pos = $this-> _nextOperator($temp);
144
145 if ($pos == -1) {
146 $this-> _error = $this-> _raiseError( 'Syntax error ');
147 $this-> _value = null;
148 return $this-> _value;
149 }
150
151 $operator = $this-> _operation[$temp[$pos]];
152 $arg = $operator[2];
153 $function = $operator[3];
154
155 if (($arg==2) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]) || !isset($temp[$pos-2]) || !is_numeric($temp[$pos-2]))) {
156 $this-> _error = $this-> _raiseError( 'Syntax error ');
157 $this-> _value = null;
158 return $this-> _value;
159 } elseif (($arg==1) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]))) {
160 $this-> _error = $this-> _raiseError( 'Syntax error ');
161 $this-> _value = null;
162 return $this-> _value;
163 }
164
165 if(is_array($function)) {
166
167 if($arg==2) $arg_array = array($temp[$pos-2],$temp[$pos-1]);
168 elseif($arg==1) $arg_array = array($temp[$pos-1]);
169 else $arg_array = array();
170
171 if($function[ 'type '] == 'userFunction ') {
172 $this-> _value = call_user_func_array($function[ 'function '], $arg_array);
173 } else {
174 $function_array = array(&$function[ 'class '], $function[ 'method ']);
175 $this-> _value = call_user_func_array($function_array, $arg_array);
176 }
177 } else {
178 $this-> _value = $this-> $function($temp, $pos);
179 }
180
181 if ($this-> _isNan($this-> _value)) {
182 $this-> _error = $this-> _raiseError( 'NAN value ');
183 $this-> _value = null;
184 return $this-> _value;
185 } elseif ($this-> _isInfinite($this-> _value)) {
186 $this-> _error = $this-> _raiseError( 'Infinite value ');
187 $this-> _value = null;
188 return $this-> _value;
189 } elseif (is_null($this-> _value)) {
190 return $this-> _value;
191 }
192
193 $temp = $this-> _refresh($temp, $pos, $arg, $this-> _value);
194 } while(count($temp) > 1);
195
196 $this-> _value = $temp[0];
197
198 $time2 = $this-> _getMicroTime();
199
200 $this-> _timer = $time2 - $time1;
201
202 return $this-> _value;
203 }
204
2
3 关于PHP计算工资问题。以下一篇文章中谈到一种计算工资的方法,称作逆波兰的算法。
4
5 我们的目标是实现如下的计算公式:
6
7 假设有一个计算公式如下:
8
9 $expression = "(F1*F12+10.34) ";
10
11 其中的变量值如下:
12
13 $expression_value = Array( 'F1 '=> 10, 'F12 '=> 20);
14
15 我们希望用PHP构建一个类来计算出这个表达式的值。这种应用主要用于web工资管理中,用户可以自定义其工资相公式的情况
16
17 $rpn = new Math_Rpn();
18 $rpn-> setExpressionValue($expression_value);
19 echo $rpn-> calculate($expression, 'deg ',false); // 即为相应的值
20
21 解析逆波兰表达式的方法,编译原理中有,就是先把表达式分解成符号数组,然后求逆波兰式,最后根据逆波兰式得到其结果。
22
23 我分别把三个函数贴在下面,其实本质我就是对Pear的RPN函数进行了Hack.
24
25 function _stringToArray () {
26 $temp_operator = null;
27 $temp_value = null;
28
29 $this-> _input = str_replace( " ", " ",$this-> _input);
30
31 for($i = 0; $i < strlen($this-> _input); $i++) {
32 if ($this-> _input[$i] == ' ') {
33 if ($temp_operator != null) {
34 array_push($this-> _input_array, $temp_operator);
35 $temp_operator = null;
36 }
37 if ($temp_value != null) {
38 array_push($this-> _input_array, $temp_value);
39 $temp_value = null;
40 }
41 } 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] == '- ')) {
42 if ($temp_operator != null) {
43 array_push($this-> _input_array, $temp_operator);
44 $temp_operator = null;
45 }
46
47 array_push($this-> _input_array, '-1 ');
48 array_push($this-> _input_array, '* ');
49 //} elseif ((is_numeric($this-> _input[$i])) || ($this-> _input[$i] == '. ')) {
50 } elseif ((is_numeric($this-> _input[$i])) || ($this-> _input[$i] == '. ') || ($this-> _input[$i] == 'F ')) {
51 if ($temp_operator != null) {
52 array_push($this-> _input_array, $temp_operator);
53 $temp_operator = null;
54 }
55
56 $temp_value .= $this-> _input[$i];
57 } else {
58 if ($this-> _keyExists($temp_operator, $this-> _operation, 1)) {
59 array_push($this-> _input_array, $temp_operator);
60 $temp_operator = null;
61 }
62
63 if ($temp_value != null) {
64 array_push($this-> _input_array, $temp_value);
65 $temp_value = null;
66 }
67
68 $temp_operator .= $this-> _input[$i];
69 }
70 }
71
72 if ($temp_operator != null && $temp_operator != ' ') {
73 array_push($this-> _input_array, $temp_operator);
74 } elseif($temp_value != null && $temp_value != ' ') {
75 array_push($this-> _input_array, $temp_value);
76 }
77
78 // $this-> _testInput();
79 print_r($this-> _expression_value);
80 print_r($this-> _input_array);
81 return $this-> _input_array;
82 }
83
84 function _arrayToRpn() {
85
86 if ($this-> _error <> null) {
87 $this-> _output = array();
88 return $this-> _output;
89 }
90
91 for($i = 0; $i < count($this-> _input_array); $i++) {
92
93 $temp = $this-> _input_array[$i];
94
95 if (is_numeric($temp)) {
96 $this-> _outputAdd($temp);
97 } else if($this-> _keyExists($temp, $this-> _expression_value, 0)) {
98 $this-> _outputAdd($this-> _expression_value[$temp]);
99 } else {
100 if ($temp == ') ') {
101 while(!$this-> _stackEmpty() && ($this-> _stackPriority() > = 1)) {
102 $this-> _outputAdd($this-> _stackDelete());
103 }
104 if (!$this-> _stackEmpty()) {
105 $this-> _stackDelete();
106 }
107
108 } elseif ($temp== '( ') {
109 $this-> _stackAdd($temp);
110 } elseif (($this-> _stackEmpty()) || (($this-> _priority($temp) > $this-> _stackPriority()))) {
111 $this-> _stackAdd($temp);
112 } else {
113 while(!$this-> _stackEmpty() && ($this-> _priority($temp) <= $this-> _stackPriority())) {
114 $this-> _outputAdd($this-> _stackDelete());
115 }
116 $this-> _stackAdd($temp);
117 }
118
119 }
120
121 }
122
123 while(!$this-> _stackEmpty()) {
124 $this-> _outputAdd($this-> _stackDelete());
125 }
126
127 return $this-> _output;
128 }
129
130 function _rpnToValue() {
131
132 $time1 = $this-> _getMicroTime();
133
134 if ($this-> _error <> null) {
135 $this-> _value = null;
136 return $this-> _value;
137 }
138
139 $this-> _value = 0;
140 $temp = $this-> _output;
141
142 do {
143 $pos = $this-> _nextOperator($temp);
144
145 if ($pos == -1) {
146 $this-> _error = $this-> _raiseError( 'Syntax error ');
147 $this-> _value = null;
148 return $this-> _value;
149 }
150
151 $operator = $this-> _operation[$temp[$pos]];
152 $arg = $operator[2];
153 $function = $operator[3];
154
155 if (($arg==2) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]) || !isset($temp[$pos-2]) || !is_numeric($temp[$pos-2]))) {
156 $this-> _error = $this-> _raiseError( 'Syntax error ');
157 $this-> _value = null;
158 return $this-> _value;
159 } elseif (($arg==1) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]))) {
160 $this-> _error = $this-> _raiseError( 'Syntax error ');
161 $this-> _value = null;
162 return $this-> _value;
163 }
164
165 if(is_array($function)) {
166
167 if($arg==2) $arg_array = array($temp[$pos-2],$temp[$pos-1]);
168 elseif($arg==1) $arg_array = array($temp[$pos-1]);
169 else $arg_array = array();
170
171 if($function[ 'type '] == 'userFunction ') {
172 $this-> _value = call_user_func_array($function[ 'function '], $arg_array);
173 } else {
174 $function_array = array(&$function[ 'class '], $function[ 'method ']);
175 $this-> _value = call_user_func_array($function_array, $arg_array);
176 }
177 } else {
178 $this-> _value = $this-> $function($temp, $pos);
179 }
180
181 if ($this-> _isNan($this-> _value)) {
182 $this-> _error = $this-> _raiseError( 'NAN value ');
183 $this-> _value = null;
184 return $this-> _value;
185 } elseif ($this-> _isInfinite($this-> _value)) {
186 $this-> _error = $this-> _raiseError( 'Infinite value ');
187 $this-> _value = null;
188 return $this-> _value;
189 } elseif (is_null($this-> _value)) {
190 return $this-> _value;
191 }
192
193 $temp = $this-> _refresh($temp, $pos, $arg, $this-> _value);
194 } while(count($temp) > 1);
195
196 $this-> _value = $temp[0];
197
198 $time2 = $this-> _getMicroTime();
199
200 $this-> _timer = $time2 - $time1;
201
202 return $this-> _value;
203 }
204