http://www.cnblogs.com/Fuss/p/3352577.html
ERP系统业务繁杂,为应对变化,通常会用到公式编辑器。联想到大学学过的汇编原理,国庆期间一个人没事干,就略微温习了下,花了几个小时写了个公式编辑器。面向对象搞多了,算法能力和记忆力都慢慢弱化了,呜呼哀哉!
本公式编辑器实现的功能很简单,就是计算加减乘除。未进行公式的校验,也未涉及逻辑运算,目的只是单纯地温习下大学的理论基础,同时希望能给其他人一些启发。采用逆波兰式算法,运行结果如下所示。下载源代码
实现代码如下:
public
class
CalculateHelper
{
//定义算术运算符的优先级
private
int
GetOperatorPriorityLevel(
char
oper)
{
switch
(oper)
{
case
'#'
:
return
0;
case
'+'
:
return
1;
case
'-'
:
return
1;
case
'*'
:
return
2;
case
'/'
:
return
2;
default
:
return
-1;
}
}
//oper1优先级高于oper2,返回正数,反之返回负数,相等则返回0
private
int
ComparePriority(
char
oper1,
char
oper2)
{
return
GetOperatorPriorityLevel(oper1) - GetOperatorPriorityLevel(oper2);
}
//中缀表达式转后缀表达式
public
Queue<
string
> MiddleToSuffix(
string
expression)
{
Stack<
char
> temporaryStack =
new
Stack<
char
>();
temporaryStack.Push(
'#'
);
Queue<
string
> suffixExpression =
new
Queue<
string
>();
string
temNum =
""
;
for
(
int
i = 0; i < expression.Length; i++)
{
if
(expression[i] ==
' '
)
//过滤空格
continue
;
#region 处理数字
if
(
char
.IsNumber(expression[i]) || expression[i] ==
'.'
)
{
temNum += expression[i];
if
((i == expression.Length - 1))
//字符串已经处理结束
suffixExpression.Enqueue(temNum);
continue
;
}
else
{
if
(temNum !=
""
)
suffixExpression.Enqueue(temNum);
temNum =
""
;
}
#endregion
#region 处理括号
if
(expression[i] ==
'('
)
temporaryStack.Push(expression[i]);
else
if
(expression[i] ==
')'
)
{
while
(temporaryStack.Peek() !=
'#'
)
//退栈并输出,直至遇到 '('
{
char
top = temporaryStack.Pop();
if
(top ==
'('
)
break
;
suffixExpression.Enqueue(top.ToString());
}
}
#endregion
#region 处理运算符
else
// 是运算符,比较优先级
{
char
top = temporaryStack.Peek();
while
(ComparePriority(expression[i], top) <= 0)
//保证栈顶元素优先级最高
{
suffixExpression.Enqueue(top.ToString());
temporaryStack.Pop();
top = temporaryStack.Peek();
}
if
(expression[i] !=
')'
)
//右括号不入栈
temporaryStack.Push(expression[i]);
}
#endregion
}
while
(temporaryStack.Count > 1)
suffixExpression.Enqueue(temporaryStack.Pop().ToString());
return
suffixExpression;
}
private
double
Calculate(
string
operand1,
string
operand2,
string
oper)
{
double
oper1 =
double
.Parse(operand1);
double
oper2 =
double
.Parse(operand2);
switch
(oper)
{
case
"+"
:
return
oper1 + oper2;
case
"-"
:
return
oper1 - oper2;
case
"*"
:
return
oper1 * oper2;
case
"/"
:
return
oper1 / oper2;
default
:
throw
new
Exception(
"操作符有误!"
);
}
}
//计算中缀表达式的结果
public
double
GetResult(
string
expression)
{
Queue<
string
> suffixExpression = MiddleToSuffix(expression);
Stack<
string
> resultStack =
new
Stack<
string
>();
while
(suffixExpression.Count() > 0)
{
string
oper = suffixExpression.Dequeue();
if
(oper ==
"+"
|| oper ==
"-"
|| oper ==
"*"
|| oper ==
"/"
)
//为操作符,就计算
{
string
oper2 = resultStack.Pop();
string
oper1 = resultStack.Pop();
string
temresult = Calculate(oper1, oper2, oper).ToString();
resultStack.Push(temresult);
}
else
resultStack.Push(oper);
}
string
result = resultStack.Pop();
return
double
.Parse(result);
}
}
|