#region 数学公式自动计算表达式
public struct MathChar
{
/// <summary>
/// +
/// </summary>
public static readonly char Add = '+';
/// <summary>
/// -
/// </summary>
public static readonly char Sub = '-';
/// <summary>
/// *
/// </summary>
public static readonly char Mul = '*';
/// <summary>
/// /
/// </summary>
public static readonly char Div = '/';
/// <summary>
/// %
/// </summary>
public static readonly char Mold = '%';
/// <summary>
/// ^
/// </summary>
public static readonly char Power = '^';
/// <summary>
/// !
/// </summary>
public static readonly char Neg = '!';
/// <summary>
/// .
/// </summary>
public static readonly char Spot = '.';
/// <summary>
/// (
/// </summary>
public static readonly char Left = '(';
/// <summary>
/// )
/// </summary>
public static readonly char Right = ')';
/// <summary>
/// ' '
/// </summary>
public static readonly char WhiteChar = ' ';
}
/// <summary>
/// Reverse Polish Notation
/// 算术逆波兰表达式.生成.
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private string BuildingExpression(string MathExpression)
{
StringBuilder ExpressionBuild = new StringBuilder(MathExpression);
Stack ExpressionStack = new Stack();
StringBuilder returnExpression = new StringBuilder();
char OneChar = MathChar.WhiteChar;
//sb.Replace(" ","");//一开始,我只去掉了空格.后来我不想不支持函数和常量能滤掉的全OUT掉.
for (int i = 0; i < ExpressionBuild.Length; i++)
{
OneChar = ExpressionBuild[i];
//保存数字
if (char.IsDigit(OneChar))
{
returnExpression.Append(OneChar);
}
//if(char.IsWhiteSpace(c)||char.IsLetter(c))//如果是空白,那么不要.现在字母也不要.
//如果是其它字符...列出的要,没有列出的不要.
switch (OneChar)
{
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
case '!':
case '(':
case ')':
case '.':
returnExpression.Append(OneChar);
break;
default:
continue;
}
}
ExpressionBuild = new StringBuilder(returnExpression.ToString());
#region 对负号进行预转义处理.负号变单目运算符求反.
for (int i = 0; i < ExpressionBuild.Length - 1; i++)
{
if (ExpressionBuild[i] == '-' && (i == 0 || ExpressionBuild[i - 1] == MathChar.Left))
{
//字符转义.
ExpressionBuild[i] = '!';
}
}
#endregion
#region 将中缀表达式变为后缀表达式.
returnExpression = new System.Text.StringBuilder();
for (int index = 0; index < ExpressionBuild.Length; index++)
{
//如果是数值.
if (char.IsDigit(ExpressionBuild[index])
|| ExpressionBuild[index] == MathChar.Spot)
{
//加入后缀式
returnExpression.Append(ExpressionBuild[index]);
}
else if (ExpressionBuild[index] == MathChar.Add
|| ExpressionBuild[index] == MathChar.Sub
|| ExpressionBuild[index] == MathChar.Mul
|| ExpressionBuild[index] == MathChar.Div
|| ExpressionBuild[index] == MathChar.Mold
|| ExpressionBuild[index] == MathChar.Power
|| ExpressionBuild[index] == MathChar.Neg)
{
#region 运算符处理
//栈不为空时
while (ExpressionStack.Count > 0)
{
//将栈中的操作符弹出.
OneChar = (char)ExpressionStack.Pop();
//如果发现左括号.停.
if (OneChar == MathChar.Left)
{
//将弹出的左括号压回.因为还有右括号要和它匹配.
ExpressionStack.Push(OneChar);
break;
}
//如果不是左括号,那么将操作符加入后缀式中.
else
{
//如果优先级比上次的高,则压栈.
if (Priority(OneChar) < Priority(ExpressionBuild[index]))
{
ExpressionStack.Push(OneChar);
break;
}
else
{
returnExpression.Append(MathChar.WhiteChar);
returnExpression.Append(OneChar);
}
}
}
//把新操作符入栈.
ExpressionStack.Push(ExpressionBuild[index]);
returnExpression.Append(MathChar.WhiteChar);
#endregion
}
//基本优先级提升
else if (ExpressionBuild[index] == MathChar.Left)
{
ExpressionStack.Push(MathChar.Left);
returnExpression.Append(MathChar.WhiteChar);
}
//基本优先级下调
else if (ExpressionBuild[index] == MathChar.Right)
{
//栈不为空时
while (ExpressionStack.Count > 0)
{
OneChar = (char)ExpressionStack.Pop();
if (OneChar != MathChar.Left)
{
returnExpression.Append(MathChar.WhiteChar);
//加入空格主要是为了防止不相干的数据相临产生解析错误.
returnExpression.Append(OneChar);
returnExpression.Append(MathChar.WhiteChar);
}
else
{
break;
}
}
}
else
{
returnExpression.Append(ExpressionBuild[index]);
}
}
while (ExpressionStack.Count > 0)//这是最后一个弹栈啦.
{
returnExpression.Append(MathChar.WhiteChar);
returnExpression.Append(ExpressionStack.Pop());
}
#endregion
returnExpression.Append(MathChar.WhiteChar);
return FormatSpace(returnExpression.ToString());//在这里进行一次表达式格式化.这里就是后缀式了.
}
/// <summary>
/// 算术逆波兰表达式计算.
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public string ComputeExpression(string MathExpression)
{
string AfterExpression = BuildingExpression(MathExpression);
string Temp = string.Empty;
Stack ExpressionStack = new Stack();
char OneChar = MathChar.WhiteChar;
StringBuilder Operand = new StringBuilder();
double x, y;
for (int i = 0; i < AfterExpression.Length; i++)
{
OneChar = AfterExpression[i];
if (char.IsDigit(OneChar)
|| OneChar == MathChar.Spot)
{
//数据值收集.
Operand.Append(OneChar);
}
else if (OneChar == MathChar.WhiteChar
&& Operand.Length > 0)
{
#region 运算数转换
try
{
Temp = Operand.ToString();
//负数的转换一定要小心...它不被直接支持.
if (Temp.StartsWith(MathChar.Sub.ToString()))
{
//现在我的算法里这个分支可能永远不会被执行.
ExpressionStack.Push(-((double)Convert.ToDouble(Temp.Substring(1, Temp.Length - 1))));
}
else
{
ExpressionStack.Push(Convert.ToDouble(Temp));
}
}
catch
{
return "发现异常数据值.";
}
Operand = new StringBuilder();
#endregion
}
//运算符处理.双目运算处理.
else if (OneChar == MathChar.Add
|| OneChar == MathChar.Sub
|| OneChar == MathChar.Mul
|| OneChar == MathChar.Div
|| OneChar == MathChar.Mold
|| OneChar == MathChar.Power)
{
#region 双目运算
if (ExpressionStack.Count > 0)/*如果输入的表达式根本没有包含运算符.或是根本就是空串.这里的逻辑就有意义了.*/
{
y = (double)ExpressionStack.Pop();
}
else
{
ExpressionStack.Push(0);
break;
}
if (ExpressionStack.Count > 0)
x = (double)ExpressionStack.Pop();
else
{
ExpressionStack.Push(y);
break;
}
switch (OneChar)
{
case '+':
ExpressionStack.Push(x + y);
break;
case '-':
ExpressionStack.Push(x - y);
break;
case '*':
ExpressionStack.Push(x * y);
break;
case '/':
ExpressionStack.Push(x / y);
break;
case '%':
ExpressionStack.Push(x % y);
break;
case '^':
// if(x>0)
// {我原本还想,如果被计算的数是负数,又要开真分数次方时如何处理的问题.后来我想还是算了吧.
ExpressionStack.Push(System.Math.Pow(x, y));
// }
// else
// {
// double t=y;
// string ts="";
// t=1/(2*t);
// ts=t.ToString();
// if(ts.ToUpper().LastIndexOf('E')>0)
// {
// ;
// }
// }
break;
}
#endregion
}
else if (OneChar == MathChar.Neg)//单目取反.)
{
ExpressionStack.Push(-((double)ExpressionStack.Pop()));
}
}
if (ExpressionStack.Count > 1)
return "运算没有完成.";
if (ExpressionStack.Count == 0)
return "结果丢失..";
return ExpressionStack.Pop().ToString();
}
/// <summary>
/// 计算表达式优先级别
/// </summary>
/// <param name="opr"></param>
/// <returns></returns>
private int Priority(char opr)
{
switch (opr)
{
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '%':
case '^':
case '!':
return 3;
default:
return 0;
}
}
/// <summary>
/// 规范化逆波兰表达式.
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private string FormatSpace(string str)
{
StringBuilder returnValue = new StringBuilder();
for (int index = 0; index < str.Length; index++)
{
if (!(str.Length > index + 1 && str[index] == ' ' && str[index + 1] == ' '))
returnValue.Append(str[index]);
else
returnValue.Append(str[index]);
}
return returnValue.ToString();
}
/// <summary>
/// 过滤数字和计算公式字符
/// </summary>
/// <param name="Expresssion"></param>
/// <returns></returns>
private string[] FilterNumberAndMathChar(string Expresssion)
{
string TempValue = Expresssion.Trim();
if (TempValue.Contains(MathChar.Add.ToString()))
{
TempValue = TempValue.Replace(MathChar.Add, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Sub.ToString()))
{
TempValue = TempValue.Replace(MathChar.Sub, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Mul.ToString()))
{
TempValue = TempValue.Replace(MathChar.Mul, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Div.ToString()))
{
TempValue = TempValue.Replace(MathChar.Div, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Neg.ToString()))
{
TempValue = TempValue.Replace(MathChar.Neg, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Mold.ToString()))
{
TempValue = TempValue.Replace(MathChar.Mold, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Power.ToString()))
{
TempValue = TempValue.Replace(MathChar.Power, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Left.ToString()))
{
TempValue = TempValue.Replace(MathChar.Left, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Right.ToString()))
{
TempValue = TempValue.Replace(MathChar.Right, MathChar.WhiteChar);
}
if (TempValue.Contains(MathChar.Spot.ToString()))
{
TempValue = TempValue.Replace(MathChar.Spot, MathChar.WhiteChar);
}
for (int index = 0; index < 10; index++)
{
if (TempValue.Contains(index.ToString()))
{
TempValue = TempValue.Replace(index.ToString(), MathChar.WhiteChar.ToString());
}
}
string[] result = TempValue.Trim().Split(new string[] { MathChar.WhiteChar.ToString() }, StringSplitOptions.RemoveEmptyEntries);
return result;
}
#endregion