[c#]代码库
/******************************************************************
* 创 建 人: SamWang
* 创建时间: 2011-11-29
* 描 述:
* 计算器类:能直接对表达式进行计算,支持变量
* 原 理: 将表达式按字符压入堆栈中,然后按照各操作符的级别进行处理
* 版 本: V1.0
* 环 境: VS2005
******************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace LingDang.CRM.UI.Client
{
public class Calculator
{
private string _expression;
private Stack s;
private string[] values;
///
/// 构造函数
///
/// 表达式
/// 变量值数组
public Calculator ( string expression, string[] varValues )
{
this._expression = expression.ToLower();
s = new Stack();
values = varValues;
}
///
/// 构造函数
///
/// 表达式
public Calculator ( string expression )
{
this._expression = expression;
s = new Stack();
}
///
/// 总运行
///
///
public double Run()
{
string expression = PostFix();
string[] aryString = expression.Split ( '|' );
foreach ( string str in aryString )
{
if ( IsNumber ( str ) || IsVarible ( str[0] ) )
{
double d;
if ( IsVarible ( str[0] ) )
{
d = Convert.ToDouble ( GetValue ( str[0] ) );
}
else
{
d = Convert.ToDouble ( str.ToString() );
}
AddOperands ( d );
}
else
{
DoOperator ( str );
}
}
return ( double ) s.Pop();
}
private bool IsNumber ( string str )
{
if ( str.Length > 1 )
{
return true;
}
else
{
return Char.IsDigit ( str[0] );
}
}
///
/// 判断是否为变量,变量范围为a-z
///
///
///
private bool IsVarible ( char c )
{
if ( c >= 'a' && c <= 'z' )
{
return true;
}
else
{
return false;
}
}
private void AddOperands ( double val )
{
s.Push ( val );
}
///
/// 得到公式左右运算数
///
///
///
///
private bool GetTwoOperands ( out double left, out double right )
{
try
{
right = ( double ) s.Pop();
left = ( double ) s.Pop();
}
catch ( InvalidOperationException )
{
right = 0;
left = 0;
return false;
}
return true;
}
///
/// 计算操作
///
/// 运算符
private void DoOperator ( string op )
{
double left, right;
bool result = GetTwoOperands ( out left, out right );
if ( result )
{
switch ( op )
{
case "+":
s.Push ( left + right );
break;
case "-":
s.Push ( left - right );
break;
case "*":
s.Push ( left * right );
break;
case "/":
if ( right == 0.0 )
{
s.Clear();
//Divide by 0!
throw new Exception ( "除数不能为零" );
}
else
s.Push ( left / right );
break;
case "^":
s.Push ( Math.Pow ( left, right ) );
break;
}
}
else
{
s.Clear();
}
}
///
/// 解析为后缀表达式
///
///
public string PostFix()
{
string str = this._expression + "#";
char tempc;
char[] chars = str.ToCharArray();
Stack ts = new Stack();
ts.Push ( '#' );
string str1 = "";
string tmpStr = "";
bool isNum = false;
foreach ( char c in chars )
{
if ( Char.IsDigit ( c ) || IsVarible ( c ) || c == '.' )
{
tmpStr += c.ToString();
isNum = true;
}
else
{
if ( isNum )
{
str1 += tmpStr + "|";
tmpStr = "";
}
isNum = false;
if ( c == ')' )
{
for ( tempc = Convert.ToChar ( ts.Pop() ); tempc != '('; tempc = Convert.ToChar ( ts.Pop() ) )
str1 += tempc.ToString() + "|";
}
else
{
for ( tempc = Convert.ToChar ( ts.Pop() ); Isp ( tempc ) > Icp ( c ); tempc = Convert.ToChar ( ts.Pop() ) )
str1 += tempc.ToString() + "|";
ts.Push ( tempc );
ts.Push ( c );
}
}
}
return str1.Substring ( 0, str1.Length - 1 );
}
///
/// 根据变量名得到对应的值
///
/// 变量名:A-Z
///
private string GetValue ( char c )
{
string result = "0";
//变量对应的数组位置
int index = Convert.ToInt32 ( c ) - Convert.ToInt32 ( 'a' );
if ( index < values.Length )
{
result = values[index].ToString();
}
return result;
}
private int Isp ( char c )
{
int k;
switch ( c )
{
case '#':
k = 0;
break;
case '(':
k = 1;
break;
case '^':
k = 7;
break;
case '*':
case '/':
case '%':
k = 5;
break;
case '+':
case '-':
k = 3;
break;
case ')':
k = 8;
break;
default:
//Unknown operator!
throw new Exception ( "无效操作符:"+c.ToString() );
}
return k;
}
private int Icp ( char c )
{
int k;
switch ( c )
{
case '#':
k = 0;
break;
case '(':
k = 8;
break;
case '^':
k = 6;
break;
case '*':
case '/':
case '%':
k = 4;
break;
case '+':
case '-':
k = 2;
break;
case ')':
k = 1;
break;
default:
//Unknown operator!
throw new Exception ( "无效操作符:" + c.ToString() );
}
return k;
}
}
}