(1)将Javasript中代码编译成.net类库,利用Javascript中的eval函数来实现;
(2)利用ScriptControl执行JavaScript脚本实现;
(3)利用DataTable的计算功能实现简单计算;
(4)利用.net动态编译功能来实现等
这些方法在csdn的坛里有讨论,请见:http://topic.csdn.net/u/20070301/13/c8c33bd1-f146-4b44-9882-aab6d430f724.html
心想既然还没有成熟的.net类库,何不自己做一个呢,其实并不难,只要稍有点耐心调试一下就好了。于是参考一编中缀表达式转后缀表达式的论文,很快写了一个,发现效果不错,所以发出来跟大家共享,希望对大家有用。
中缀表达式转后缀表达式的步骤为:
1.新建一个Stack栈,用来存放运算符
2.新建一个post栈,用来存放最后的后缀表达式
3.从左到右扫描中缀表达式:
(1)若读到的是操作数,直接存入post栈,以#作为数字的结束
(2)若读到的是(,则直接存入stack栈
(3)若读到的是),则将stack栈中(前的所有运算符出栈,存入post栈
(4)若读到的是其它运算符,则将该运算符和stack栈顶运算符作比较:若高于或等于栈顶运算符,则直接存入stack栈,否则将栈顶运算符(所有优先级高于读到的运算符的,不包括括号)出栈,存入post栈。最后将读到的运算符入栈。
4.当扫描完后,stack栈中还在运算符时,则将所有的运算符出栈,存入post栈
计算后缀表达式的值的步骤为:
1.初始化一个空堆栈
2.从左到右读入后缀表达式
3.如果字符是一个操作数,把它压入堆栈。
4.如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。
5.到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
类库的名称就名为NEval ,感觉还比较健壮,速度很快,支持20个数学函数,很容易扩充。目前还没有表达式合法性检查的功能,有兴趣的朋友可以扩充一下,先谢谢。
代码如下:
代码
///
<summary>
/// 表达式计算类。支持数学函数,支持函数嵌套
/// 作者watsonyin
/// 开发日期:2010年10月 版本1.0
/// </summary>
public class NEval
{
public NEval()
{
}
public double Eval( string expr)
{
try
{
string tmpexpr = expr.ToLower().Trim().Replace( " " , string .Empty);
return Calc_Internal(tmpexpr);
}
catch (ExpressionException eex)
{
throw eex;
}
catch
{
throw new Exception( " 表达式错误 " );
}
}
private Random m_Random = null ;
private double Calc_Internal( string expr)
{
/*
* 1. 初始化一个空堆栈
* 2. 从左到右读入后缀表达式
* 3. 如果字符是一个操作数,把它压入堆栈。
* 4. 如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。
* 5. 到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
*/
Stack post2 = ConvertExprBack(expr);
Stack post = new Stack();
while (post2.Count > 0 )
post.Push(post2.Pop());
Stack stack = new Stack();
while (post.Count > 0 )
{
string tmpstr = post.Pop().ToString();
char c = tmpstr[ 0 ];
LetterType lt = JudgeLetterType(tmpstr);
if (lt == LetterType.Number)
{
stack.Push(tmpstr);
}
else if (lt == LetterType.SimpleOperator)
{
double d1 = double .Parse(stack.Pop().ToString());
double d2 = double .Parse(stack.Pop().ToString());
double r = 0 ;
if (c == ' + ' )
r = d2 + d1;
else if (c == ' - ' )
r = d2 - d1;
else if (c == ' * ' )
r = d2 * d1;
else if (c == ' / ' )
r = d2 / d1;
else if (c == ' ^ ' )
r = Math.Pow(d2, d1);
else
throw new Exception( " 不支持操作符: " + c.ToString());
stack.Push(r);
}
else if (lt == LetterType.Function) // 如果是函数
{
string [] p;
double d = 0 ;
double d1 = 0 ;
double d2 = 0 ;
int tmpos = tmpstr.IndexOf( ' ( ' );
string funcName = tmpstr.Substring( 0 , tmpos);
switch (funcName)
{
case " asin " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Asin(d).ToString());
break ;
case " acos " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Acos(d).ToString());
break ;
case " atan " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Atan(d).ToString());
break ;
case " acot " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(( 1 / Math.Atan(d)).ToString());
break ;
case " sin " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Sin(d).ToString());
break ;
case " cos " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Cos(d).ToString());
break ;
case " tan " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Tan(d).ToString());
break ;
case " cot " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(( 1 / Math.Tan(d)).ToString());
break ;
case " log " :
SplitFuncStr(tmpstr, 2 , out p);
d1 = double .Parse(p[ 0 ]);
d2 = double .Parse(p[ 1 ]);
stack.Push(Math.Log(d1, d2).ToString());
break ;
case " ln " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Log(d, Math.E).ToString());
break ;
case " abs " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Abs(d).ToString());
break ;
case " round " :
SplitFuncStr(tmpstr, 2 , out p);
d1 = double .Parse(p[ 0 ]);
d2 = double .Parse(p[ 1 ]);
stack.Push(Math.Round(d1, ( int )d2).ToString());
break ;
case " int " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(( int )d);
break ;
case " trunc " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Truncate(d).ToString());
break ;
case " floor " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Floor(d).ToString());
break ;
case " ceil " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Ceiling(d).ToString());
break ;
case " random " :
if (m_Random == null )
m_Random = new Random();
d = m_Random.NextDouble();
stack.Push(d.ToString());
break ;
case " exp " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Exp(d).ToString());
break ;
case " pow " :
SplitFuncStr(tmpstr, 2 , out p);
d1 = double .Parse(p[ 0 ]);
d2 = double .Parse(p[ 1 ]);
stack.Push(Math.Pow(d1, d2).ToString());
break ;
case " sqrt " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Sqrt(d).ToString());
break ;
default :
throw new Exception( " 未定义的函数: " + funcName);
}
}
}
object obj = stack.Pop();
return double .Parse(obj.ToString());
}
/// <summary>
/// 将函数括号内的字符串进行分割,获得参数列表,如果参数是嵌套的函数,用递归法计算得到它的值
/// </summary>
/// <param name="funcstr"></param>
/// <param name="paramCount"></param>
/// <param name="parameters"></param>
private void SplitFuncStr( string funcstr, int paramCount, out string [] parameters)
{
parameters = new string [paramCount];
int tmpPos = funcstr.IndexOf( ' ( ' , 0 );
string str = funcstr.Substring(tmpPos + 1 , funcstr.Length - tmpPos - 2 );
if (paramCount == 1 )
{
parameters[ 0 ] = str;
}
else
{
int cpnum = 0 ;
int startPos = 0 ;
int paramIndex = 0 ;
for ( int i = 0 ; i <= str.Length - 1 ; i ++ )
{
if (str[i] == ' ( ' )
cpnum ++ ;
else if (str[i] == ' ) ' )
cpnum -- ;
else if (str[i] == ' , ' )
{
if (cpnum == 0 )
{
string tmpstr = str.Substring(startPos, i - startPos);
parameters[paramIndex] = tmpstr;
paramIndex ++ ;
startPos = i + 1 ;
}
}
}
if (startPos < str.Length)
{
string tmpstr = str.Substring(startPos);
parameters[paramIndex] = tmpstr;
}
}
// 如果参数是函数, 进一步采用递归的方法生成函数值
for ( int i = 0 ; i <= paramCount - 1 ; i ++ )
{
double d;
if ( ! double .TryParse(parameters[i], out d))
{
NEval calc = new NEval();
d = calc.Eval(parameters[i]);
parameters[i] = d.ToString();
}
}
}
/// <summary>
/// 将中缀表达式转为后缀表达式
/// </summary>
/// <param name="expr"></param>
/// <returns></returns>
private Stack ConvertExprBack( string expr)
{
/*
* 新建一个Stack栈,用来存放运算符
* 新建一个post栈,用来存放最后的后缀表达式
* 从左到右扫描中缀表达式:
* 1.若读到的是操作数,直接存入post栈,以#作为数字的结束
* 2、若读到的是(,则直接存入stack栈
* 3.若读到的是),则将stack栈中(前的所有运算符出栈,存入post栈
* 4 若读到的是其它运算符,则将该运算符和stack栈顶运算符作比较:若高于或等于栈顶运算符, 则直接存入stack栈,
* 否则将栈顶运算符(所有优先级高于读到的运算符的,不包括括号)出栈,存入post栈。最后将读到的运算符入栈
* 当扫描完后,stack栈中还在运算符时,则将所有的运算符出栈,存入post栈
* */
Stack post = new Stack();
Stack stack = new Stack();
string tmpstr;
int pos;
for ( int i = 0 ; i <= expr.Length - 1 ; i ++ )
{
char c = expr[i];
LetterType lt = JudgeLetterType(c, expr, i);
if (lt == LetterType.Number) // 操作数
{
GetCompleteNumber(expr, i, out tmpstr, out pos);
post.Push(tmpstr);
i = pos; // +1;
}
else if (lt == LetterType.OpeningParenthesis) // 左括号(
{
stack.Push(c);
}
else if (lt == LetterType.ClosingParenthesis) // 右括号)
{
while (stack.Count > 0 )
{
if (stack.Peek().ToString() == " ( " )
{
stack.Pop();
break ;
}
else
post.Push(stack.Pop());
}
}
else if (lt == LetterType.SimpleOperator) // 其它运算符
{
if (stack.Count == 0 )
stack.Push(c);
else
{
char tmpop = ( char )stack.Peek();
if (tmpop == ' ( ' )
{
stack.Push(c);
}
else
{
if (GetPriority(c) >= GetPriority(tmpop))
{
stack.Push(c);
}
else
{
while (stack.Count > 0 )
{
object tmpobj = stack.Peek();
if (GetPriority(( char )tmpobj) > GetPriority(c))
{
if (tmpobj.ToString() != " ( " )
post.Push(stack.Pop());
else
break ;
}
else
break ;
}
stack.Push(c);
}
}
}
}
else if (lt == LetterType.Function) // 如果是一个函数,则完整取取出函数,当作一个操作数处理
{
GetCompleteFunction(expr, i, out tmpstr, out pos);
post.Push(tmpstr);
i = pos; // +1;
}
}
while (stack.Count > 0 )
{
post.Push(stack.Pop());
}
return post;
}
private LetterType JudgeLetterType( char c, string expr, int pos)
{
string op = " */^ " ;
if ((c <= ' 9 ' && c >= ' 0 ' ) || (c == ' . ' )) // 操作数
{
return LetterType.Number;
}
else if (c == ' ( ' )
{
return LetterType.OpeningParenthesis;
}
else if (c == ' ) ' )
{
return LetterType.ClosingParenthesis;
}
else if (op.IndexOf(c) >= 0 )
{
return LetterType.SimpleOperator;
}
else if ((c == ' - ' ) || (c == ' + ' )) // 要判断是减号还是负数
{
if (pos == 0 )
return LetterType.Number;
else
{
char tmpc = expr[pos - 1 ];
if (tmpc <= ' 9 ' && tmpc >= ' 0 ' ) // 如果前面一位是操作数
return LetterType.SimpleOperator;
else if (tmpc == ' ) ' )
return LetterType.SimpleOperator;
else
return LetterType.Number;
}
}
else
return LetterType.Function;
}
private LetterType JudgeLetterType( char c)
{
string op = " +-*/^ " ;
if ((c <= ' 9 ' && c >= ' 0 ' ) || (c == ' . ' )) // 操作数
{
return LetterType.Number;
}
else if (c == ' ( ' )
{
return LetterType.OpeningParenthesis;
}
else if (c == ' ) ' )
{
return LetterType.ClosingParenthesis;
}
else if (op.IndexOf(c) >= 0 )
{
return LetterType.SimpleOperator;
}
else
return LetterType.Function;
}
private LetterType JudgeLetterType( string s)
{
char c = s[ 0 ];
if ((c == ' - ' ) || (c == ' + ' ))
{
if (s.Length > 1 )
return LetterType.Number;
else
return LetterType.SimpleOperator;
}
string op = " +-*/^ " ;
if ((c <= ' 9 ' && c >= ' 0 ' ) || (c == ' . ' )) // 操作数
{
return LetterType.Number;
}
else if (c == ' ( ' )
{
return LetterType.OpeningParenthesis;
}
else if (c == ' ) ' )
{
return LetterType.ClosingParenthesis;
}
else if (op.IndexOf(c) >= 0 )
{
return LetterType.SimpleOperator;
}
else
return LetterType.Function;
}
/// <summary>
/// 计算操作符的优先级
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
private int GetPriority( char c)
{
if (c == ' + ' || c == ' - ' )
return 0 ;
else if (c == ' * ' )
return 1 ;
else if (c == ' / ' ) // 除号优先级要设得比乘号高,否则分母可能会被先运算掉
return 2 ;
else
return 2 ;
}
/// <summary>
/// 获取完整的函数表达式
/// </summary>
/// <param name="expr"></param>
/// <param name="startPos"></param>
/// <param name="funcStr"></param>
/// <param name="endPos"></param>
private void GetCompleteFunction( string expr, int startPos, out string funcStr, out int endPos)
{
int cpnum = 0 ;
for ( int i = startPos; i <= expr.Length - 1 ; i ++ )
{
char c = expr[i];
LetterType lt = JudgeLetterType(c);
if (lt == LetterType.OpeningParenthesis)
cpnum ++ ;
else if (lt == LetterType.ClosingParenthesis)
{
cpnum -- ; // 考虑到函数嵌套的情况,消除掉内部括号
if (cpnum == 0 )
{
endPos = i;
funcStr = expr.Substring(startPos, endPos - startPos + 1 );
return ;
}
}
}
funcStr = "" ;
endPos = - 1 ;
}
/// <summary>
/// 获取到完整的数字
/// </summary>
/// <param name="expr"></param>
/// <param name="startPos"></param>
/// <param name="numberStr"></param>
/// <param name="endPos"></param>
private void GetCompleteNumber( string expr, int startPos, out string numberStr, out int endPos)
{
char c = expr[startPos];
for ( int i = startPos + 1 ; i <= expr.Length - 1 ; i ++ )
{
char tmpc = expr[i];
if (JudgeLetterType(tmpc) != LetterType.Number)
{
endPos = i - 1 ;
numberStr = expr.Substring(startPos, endPos - startPos + 1 );
return ;
}
}
numberStr = expr.Substring(startPos);
endPos = expr.Length - 1 ;
}
}
/// <summary>
/// 可以检测到的表达式错误的Exception
/// </summary>
public class ExpressionException : Exception
{
public override string Message
{
get
{
return base .Message;
}
}
}
/// <summary>
/// 字符类别
/// </summary>
public enum LetterType
{
Number,
SimpleOperator,
Function,
OpeningParenthesis,
ClosingParenthesis
}
/// 表达式计算类。支持数学函数,支持函数嵌套
/// 作者watsonyin
/// 开发日期:2010年10月 版本1.0
/// </summary>
public class NEval
{
public NEval()
{
}
public double Eval( string expr)
{
try
{
string tmpexpr = expr.ToLower().Trim().Replace( " " , string .Empty);
return Calc_Internal(tmpexpr);
}
catch (ExpressionException eex)
{
throw eex;
}
catch
{
throw new Exception( " 表达式错误 " );
}
}
private Random m_Random = null ;
private double Calc_Internal( string expr)
{
/*
* 1. 初始化一个空堆栈
* 2. 从左到右读入后缀表达式
* 3. 如果字符是一个操作数,把它压入堆栈。
* 4. 如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。
* 5. 到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
*/
Stack post2 = ConvertExprBack(expr);
Stack post = new Stack();
while (post2.Count > 0 )
post.Push(post2.Pop());
Stack stack = new Stack();
while (post.Count > 0 )
{
string tmpstr = post.Pop().ToString();
char c = tmpstr[ 0 ];
LetterType lt = JudgeLetterType(tmpstr);
if (lt == LetterType.Number)
{
stack.Push(tmpstr);
}
else if (lt == LetterType.SimpleOperator)
{
double d1 = double .Parse(stack.Pop().ToString());
double d2 = double .Parse(stack.Pop().ToString());
double r = 0 ;
if (c == ' + ' )
r = d2 + d1;
else if (c == ' - ' )
r = d2 - d1;
else if (c == ' * ' )
r = d2 * d1;
else if (c == ' / ' )
r = d2 / d1;
else if (c == ' ^ ' )
r = Math.Pow(d2, d1);
else
throw new Exception( " 不支持操作符: " + c.ToString());
stack.Push(r);
}
else if (lt == LetterType.Function) // 如果是函数
{
string [] p;
double d = 0 ;
double d1 = 0 ;
double d2 = 0 ;
int tmpos = tmpstr.IndexOf( ' ( ' );
string funcName = tmpstr.Substring( 0 , tmpos);
switch (funcName)
{
case " asin " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Asin(d).ToString());
break ;
case " acos " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Acos(d).ToString());
break ;
case " atan " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Atan(d).ToString());
break ;
case " acot " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(( 1 / Math.Atan(d)).ToString());
break ;
case " sin " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Sin(d).ToString());
break ;
case " cos " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Cos(d).ToString());
break ;
case " tan " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Tan(d).ToString());
break ;
case " cot " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(( 1 / Math.Tan(d)).ToString());
break ;
case " log " :
SplitFuncStr(tmpstr, 2 , out p);
d1 = double .Parse(p[ 0 ]);
d2 = double .Parse(p[ 1 ]);
stack.Push(Math.Log(d1, d2).ToString());
break ;
case " ln " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Log(d, Math.E).ToString());
break ;
case " abs " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Abs(d).ToString());
break ;
case " round " :
SplitFuncStr(tmpstr, 2 , out p);
d1 = double .Parse(p[ 0 ]);
d2 = double .Parse(p[ 1 ]);
stack.Push(Math.Round(d1, ( int )d2).ToString());
break ;
case " int " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(( int )d);
break ;
case " trunc " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Truncate(d).ToString());
break ;
case " floor " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Floor(d).ToString());
break ;
case " ceil " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Ceiling(d).ToString());
break ;
case " random " :
if (m_Random == null )
m_Random = new Random();
d = m_Random.NextDouble();
stack.Push(d.ToString());
break ;
case " exp " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Exp(d).ToString());
break ;
case " pow " :
SplitFuncStr(tmpstr, 2 , out p);
d1 = double .Parse(p[ 0 ]);
d2 = double .Parse(p[ 1 ]);
stack.Push(Math.Pow(d1, d2).ToString());
break ;
case " sqrt " :
SplitFuncStr(tmpstr, 1 , out p);
d = double .Parse(p[ 0 ]);
stack.Push(Math.Sqrt(d).ToString());
break ;
default :
throw new Exception( " 未定义的函数: " + funcName);
}
}
}
object obj = stack.Pop();
return double .Parse(obj.ToString());
}
/// <summary>
/// 将函数括号内的字符串进行分割,获得参数列表,如果参数是嵌套的函数,用递归法计算得到它的值
/// </summary>
/// <param name="funcstr"></param>
/// <param name="paramCount"></param>
/// <param name="parameters"></param>
private void SplitFuncStr( string funcstr, int paramCount, out string [] parameters)
{
parameters = new string [paramCount];
int tmpPos = funcstr.IndexOf( ' ( ' , 0 );
string str = funcstr.Substring(tmpPos + 1 , funcstr.Length - tmpPos - 2 );
if (paramCount == 1 )
{
parameters[ 0 ] = str;
}
else
{
int cpnum = 0 ;
int startPos = 0 ;
int paramIndex = 0 ;
for ( int i = 0 ; i <= str.Length - 1 ; i ++ )
{
if (str[i] == ' ( ' )
cpnum ++ ;
else if (str[i] == ' ) ' )
cpnum -- ;
else if (str[i] == ' , ' )
{
if (cpnum == 0 )
{
string tmpstr = str.Substring(startPos, i - startPos);
parameters[paramIndex] = tmpstr;
paramIndex ++ ;
startPos = i + 1 ;
}
}
}
if (startPos < str.Length)
{
string tmpstr = str.Substring(startPos);
parameters[paramIndex] = tmpstr;
}
}
// 如果参数是函数, 进一步采用递归的方法生成函数值
for ( int i = 0 ; i <= paramCount - 1 ; i ++ )
{
double d;
if ( ! double .TryParse(parameters[i], out d))
{
NEval calc = new NEval();
d = calc.Eval(parameters[i]);
parameters[i] = d.ToString();
}
}
}
/// <summary>
/// 将中缀表达式转为后缀表达式
/// </summary>
/// <param name="expr"></param>
/// <returns></returns>
private Stack ConvertExprBack( string expr)
{
/*
* 新建一个Stack栈,用来存放运算符
* 新建一个post栈,用来存放最后的后缀表达式
* 从左到右扫描中缀表达式:
* 1.若读到的是操作数,直接存入post栈,以#作为数字的结束
* 2、若读到的是(,则直接存入stack栈
* 3.若读到的是),则将stack栈中(前的所有运算符出栈,存入post栈
* 4 若读到的是其它运算符,则将该运算符和stack栈顶运算符作比较:若高于或等于栈顶运算符, 则直接存入stack栈,
* 否则将栈顶运算符(所有优先级高于读到的运算符的,不包括括号)出栈,存入post栈。最后将读到的运算符入栈
* 当扫描完后,stack栈中还在运算符时,则将所有的运算符出栈,存入post栈
* */
Stack post = new Stack();
Stack stack = new Stack();
string tmpstr;
int pos;
for ( int i = 0 ; i <= expr.Length - 1 ; i ++ )
{
char c = expr[i];
LetterType lt = JudgeLetterType(c, expr, i);
if (lt == LetterType.Number) // 操作数
{
GetCompleteNumber(expr, i, out tmpstr, out pos);
post.Push(tmpstr);
i = pos; // +1;
}
else if (lt == LetterType.OpeningParenthesis) // 左括号(
{
stack.Push(c);
}
else if (lt == LetterType.ClosingParenthesis) // 右括号)
{
while (stack.Count > 0 )
{
if (stack.Peek().ToString() == " ( " )
{
stack.Pop();
break ;
}
else
post.Push(stack.Pop());
}
}
else if (lt == LetterType.SimpleOperator) // 其它运算符
{
if (stack.Count == 0 )
stack.Push(c);
else
{
char tmpop = ( char )stack.Peek();
if (tmpop == ' ( ' )
{
stack.Push(c);
}
else
{
if (GetPriority(c) >= GetPriority(tmpop))
{
stack.Push(c);
}
else
{
while (stack.Count > 0 )
{
object tmpobj = stack.Peek();
if (GetPriority(( char )tmpobj) > GetPriority(c))
{
if (tmpobj.ToString() != " ( " )
post.Push(stack.Pop());
else
break ;
}
else
break ;
}
stack.Push(c);
}
}
}
}
else if (lt == LetterType.Function) // 如果是一个函数,则完整取取出函数,当作一个操作数处理
{
GetCompleteFunction(expr, i, out tmpstr, out pos);
post.Push(tmpstr);
i = pos; // +1;
}
}
while (stack.Count > 0 )
{
post.Push(stack.Pop());
}
return post;
}
private LetterType JudgeLetterType( char c, string expr, int pos)
{
string op = " */^ " ;
if ((c <= ' 9 ' && c >= ' 0 ' ) || (c == ' . ' )) // 操作数
{
return LetterType.Number;
}
else if (c == ' ( ' )
{
return LetterType.OpeningParenthesis;
}
else if (c == ' ) ' )
{
return LetterType.ClosingParenthesis;
}
else if (op.IndexOf(c) >= 0 )
{
return LetterType.SimpleOperator;
}
else if ((c == ' - ' ) || (c == ' + ' )) // 要判断是减号还是负数
{
if (pos == 0 )
return LetterType.Number;
else
{
char tmpc = expr[pos - 1 ];
if (tmpc <= ' 9 ' && tmpc >= ' 0 ' ) // 如果前面一位是操作数
return LetterType.SimpleOperator;
else if (tmpc == ' ) ' )
return LetterType.SimpleOperator;
else
return LetterType.Number;
}
}
else
return LetterType.Function;
}
private LetterType JudgeLetterType( char c)
{
string op = " +-*/^ " ;
if ((c <= ' 9 ' && c >= ' 0 ' ) || (c == ' . ' )) // 操作数
{
return LetterType.Number;
}
else if (c == ' ( ' )
{
return LetterType.OpeningParenthesis;
}
else if (c == ' ) ' )
{
return LetterType.ClosingParenthesis;
}
else if (op.IndexOf(c) >= 0 )
{
return LetterType.SimpleOperator;
}
else
return LetterType.Function;
}
private LetterType JudgeLetterType( string s)
{
char c = s[ 0 ];
if ((c == ' - ' ) || (c == ' + ' ))
{
if (s.Length > 1 )
return LetterType.Number;
else
return LetterType.SimpleOperator;
}
string op = " +-*/^ " ;
if ((c <= ' 9 ' && c >= ' 0 ' ) || (c == ' . ' )) // 操作数
{
return LetterType.Number;
}
else if (c == ' ( ' )
{
return LetterType.OpeningParenthesis;
}
else if (c == ' ) ' )
{
return LetterType.ClosingParenthesis;
}
else if (op.IndexOf(c) >= 0 )
{
return LetterType.SimpleOperator;
}
else
return LetterType.Function;
}
/// <summary>
/// 计算操作符的优先级
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
private int GetPriority( char c)
{
if (c == ' + ' || c == ' - ' )
return 0 ;
else if (c == ' * ' )
return 1 ;
else if (c == ' / ' ) // 除号优先级要设得比乘号高,否则分母可能会被先运算掉
return 2 ;
else
return 2 ;
}
/// <summary>
/// 获取完整的函数表达式
/// </summary>
/// <param name="expr"></param>
/// <param name="startPos"></param>
/// <param name="funcStr"></param>
/// <param name="endPos"></param>
private void GetCompleteFunction( string expr, int startPos, out string funcStr, out int endPos)
{
int cpnum = 0 ;
for ( int i = startPos; i <= expr.Length - 1 ; i ++ )
{
char c = expr[i];
LetterType lt = JudgeLetterType(c);
if (lt == LetterType.OpeningParenthesis)
cpnum ++ ;
else if (lt == LetterType.ClosingParenthesis)
{
cpnum -- ; // 考虑到函数嵌套的情况,消除掉内部括号
if (cpnum == 0 )
{
endPos = i;
funcStr = expr.Substring(startPos, endPos - startPos + 1 );
return ;
}
}
}
funcStr = "" ;
endPos = - 1 ;
}
/// <summary>
/// 获取到完整的数字
/// </summary>
/// <param name="expr"></param>
/// <param name="startPos"></param>
/// <param name="numberStr"></param>
/// <param name="endPos"></param>
private void GetCompleteNumber( string expr, int startPos, out string numberStr, out int endPos)
{
char c = expr[startPos];
for ( int i = startPos + 1 ; i <= expr.Length - 1 ; i ++ )
{
char tmpc = expr[i];
if (JudgeLetterType(tmpc) != LetterType.Number)
{
endPos = i - 1 ;
numberStr = expr.Substring(startPos, endPos - startPos + 1 );
return ;
}
}
numberStr = expr.Substring(startPos);
endPos = expr.Length - 1 ;
}
}
/// <summary>
/// 可以检测到的表达式错误的Exception
/// </summary>
public class ExpressionException : Exception
{
public override string Message
{
get
{
return base .Message;
}
}
}
/// <summary>
/// 字符类别
/// </summary>
public enum LetterType
{
Number,
SimpleOperator,
Function,
OpeningParenthesis,
ClosingParenthesis
}
调用代码如下:
string expr = txtExpression.Text;
NEval neval = new NEval();
return neval.Eval(expr);