`
webcode
  • 浏览: 6165744 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

我就给一个PHP逆波兰表达式的算法吧---工资计算专用

阅读更多

有个网友写信给我谈到关于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;
}

分享到:
评论

相关推荐

    逆波兰表达式及其算法实现

    ### 逆波兰表达式及其算法实现 #### 一、引言 逆波兰表达式(Reverse Polish Notation, RPN)是一种特殊的数学表达式表示方法,它最初由波兰逻辑学家Jan Łukasiewicz提出。与传统的中缀表达式相比,逆波兰表达式...

    转化为逆波兰表达式

    C语言:设计一个算法,将一般算术表达式转化为逆波兰表达式,并求逆波兰表达式的值。数据结构实验

    python-leetcode面试题解之第150题逆波兰表达式求值-题解.zip

    逆波兰表达式(Reverse Polish Notation,RPN)是一种数学表达式表示方法,它将操作符放在操作数之后,使得表达式无需括号就能清晰地表明运算顺序。在本题中,我们需要用Python来实现一个逆波兰表达式求值器。这在...

    逆波兰表达式

    总的来说,逆波兰表达式是计算机科学中解决计算问题的一种有效工具,它涉及到的数据结构和算法概念如堆栈、队列和链表,都是计算机科学基础中的核心知识点。理解并熟练运用这些知识对于编写高效的代码和解决问题至关...

    基于逆波兰表达式的科学计算机源码

    本项目提供了一个基于逆波兰表达式的科学计算器的源码,非常适合学习者深入理解计算原理和编程实现。 首先,我们要了解逆波兰表达式的工作原理。在普通中缀表达式(如2 + 3 * 4)中,运算符位于操作数之间,而在逆...

    逆波兰表达式的C++实现

    通过这样的实现,我们可以有效地计算逆波兰表达式,不仅简化了表达式的求值过程,还提高了计算效率。逆波兰表达式在编译器设计、计算器程序以及其他需要解析和计算数学表达式的地方都有广泛的应用。

    逆波兰表达式计算易语言源码-易语言.zip

    逆波兰表达式计算源码是实现逆波兰表达式求值的程序代码。在易语言中,我们可以利用栈这一数据结构来实现逆波兰表达式的计算。栈是一种先进后出(FILO)的数据结构,非常适合处理后缀表达式,因为它可以按运算符出现...

    用java和逆波兰表达式写的计算器

    4. **后缀表达式计算**:在得到逆波兰表达式后,我们可以通过遍历后缀表达式的每一个元素来计算结果。如果是数字,直接压栈;如果是运算符,就取出栈顶的两个元素进行运算,并将结果压回栈。 5. **异常处理**:在...

    04-G 逆波兰表达式1

    在处理完中缀表达式后,我们可以用这个逆波兰表达式和一个辅助栈来计算表达式的值,每次遇到操作符就取出相应的操作数进行计算,然后将结果压回栈。 总结来说,逆波兰表达式通过消除括号和优先级的概念,简化了...

    算法-逆波兰表达式(信息学奥赛一本通-T1198)(包含源程序).rar

    在提供的源程序中,可能包含了实现逆波兰表达式计算的算法,选手可以通过阅读源代码学习如何高效地解决这类问题。源程序可能使用了C、C++、Python等编程语言,通过分析代码逻辑,可以深入理解栈的运用和逆波兰表达式...

    libolan.rar_site:www.pudn.com_逆波兰_逆波兰式_逆波兰表达式

    逆波兰表达式,又称后缀表达式,是计算机科学中的一种数学表达式表示法,它在计算和编译原理领域有着广泛的应用。这种表达式的主要特点是操作符位于其操作数之后,与我们常见的中缀表达式(操作数在操作符之间)有所...

    栈与逆波兰表达式(VC++源程序)

    在计算逆波兰表达式时,我们通常会用到两个栈:一个用来存储操作数,另一个用来存储运算符。以下是利用栈计算逆波兰表达式的步骤: 1. 初始化两个空栈,一个为操作数栈,一个为运算符栈。 2. 从左到右扫描逆波兰...

    逆波兰表达式计算器

    逆波兰表达式(Reverse Polish Notation...总的来说,逆波兰表达式计算器项目是理解和实现计算逻辑的一个良好实践,同时也提供了扩展和自定义的可能性,对于学习数据结构和算法,特别是栈的应用,具有很高的教育价值。

    什么是逆波兰表达式?详细讲解!

    与我们常见的中缀表达式(运算符位于操作数之间)不同,逆波兰表达式将运算符放在操作数之后,这种表示方式在计算机科学中有着广泛的应用,特别是在编译原理、算法设计和计算模型等领域。 在逆波兰表达式中,计算...

    表达式求值源代码(逆波兰式)

    逆波兰表达式,又称后缀表达式,是一种数学表达式的表示方法,它将运算符放在操作数之后,以此简化表达式求值的过程。在逆波兰表达式中,不需要使用括号来表明运算的优先级,而是通过运算符的顺序来决定。这种表示法...

    逆波兰算术表达式解析的JavaScript实现

    逆波兰算术表达式,又称后缀表达式,是一种没有括号且运算符放在操作数后面的表示法。这种表示方式简化了表达式的计算过程,特别适用于计算机程序处理。本篇文章将探讨如何使用JavaScript来实现逆波兰算术表达式解析...

    中缀表达式转化逆波兰表达式

    逆波兰表达式,又称后缀表达式,是一种在编译原理和计算机科学中常见的表示算术或逻辑表达式的方式。它的特点在于运算符位于其操作数之后,这与我们常用的中缀表达式(运算符位于操作数之间)形成了鲜明对比。在中缀...

    1. 实验3 逆波兰式的产生及计算-预习提示1

    逆波兰式是一种表达算术表达式的方式,它的特点是运算符写在操作数之后,便于计算机进行计算。 1. **逆波兰式定义**: 逆波兰式是一种后缀表示法,运算对象在前,运算符在后。这种表示方式简化了计算过程,因为...

    编译原理实验 (计算器 语法树 逆波兰表达式)

    本实验“编译原理 实验 (计算器 语法树 逆波兰表达式)”着重于理解和应用编译器的一些核心概念,特别是与计算、语法分析和后缀表达式相关的部分。 首先,我们关注“计算器”部分。一个计算器程序通常包含输入解析...

    使用逆波兰表达式实现的四则运算解析库计算器

    开发者可能通过实例化一个计算器对象,然后调用其方法来解析和计算逆波兰表达式。阅读和理解这个项目可以加深对逆波兰表达式、栈数据结构以及JavaScript编程的理解,对于提升编程技能和解决问题的能力大有裨益。

Global site tag (gtag.js) - Google Analytics