第1个回答 2008-12-17
不支持负号,当然想用的话用 0- 代替 -
加减乘除括号以及若干函数,函数可以你自己添加。
在
if (aExp.Contains("sin"))
{
function(ref aExp, "sin");
}
这个地方加上就行了。
using System;
using System.Collections.Generic;
using System.Text;
namespace sizeyunsuan
{
class Program
{
static void Main(string[] args)
{
string a = Convert.ToString(23.0);
double value1 = 100 * (15 - 23 / (22.11 + 1.2341141242341142341251)) + 28.01 * Math.Sin(100);
double value2 = Arithmetic_expression.Calculate("100*(15-23/(22.11+1.2341141242341142341251))+28.01*sin(100)");
Console.WriteLine(value1.ToString());
Console.WriteLine(value2.ToString());
Console.ReadLine();
}
}
public class Arithmetic_expression
{
public static double Calculate(string aExp)
{
aExp = aExp.ToLower();
if (aExp.Contains("sin"))
{
function(ref aExp, "sin");
}
if (aExp.Contains("cos"))
{
function(ref aExp, "cos");
}
if (aExp.Contains("sqrt"))
{
function(ref aExp, "sqrt");
}
Stack<double> numStack = new Stack<double>();
Stack<char> opeStack = new Stack<char>();
opeStack.Push('#');
//Make a label end of string.
aExp += "#";
int pos = 0;
string tmpString = "";
//First, put numbers or operation into sracks.
while (pos < aExp.Length || opeStack.Peek() != '#')
{
if (!isNum(aExp[pos]))
{
switch (preOperator(aExp[pos], opeStack.Peek()))
{
case '>':
opeStack.Push(aExp[pos]);
pos++;
break;
case '<'://Calculate!
numStack.Push(compute(numStack.Pop(), numStack.Pop(), opeStack.Pop()));
break;
default:
opeStack.Pop();
pos++;
break;
}
tmpString = "";
}
else
{
if (numStack.Count > 0)
{
if (pos == 0)
{
numStack.Push(aExp[0]);
pos++;
continue;
}
if (!isNum(aExp[pos - 1]))
{
numStack.Push(0);
}
double tmpDouble = numStack.Pop();
if (aExp[pos] == '.')
{
}
else if (!tmpString.Contains(".") && aExp[pos - 1] != '.')
{
tmpDouble = tmpDouble * 10 + int.Parse(aExp.Substring(pos, 1));
}
else if (!tmpString.Contains(".") && aExp[pos - 1] == '.')
{
//Decimal.
tmpDouble = tmpDouble + int.Parse(aExp.Substring(pos, 1)) * 0.1;
}
else if (tmpString.Contains("."))
{
//Decimal.
int l = tmpString.Split(new char[1] { '.' })[1].Length + 1;
tmpDouble = tmpDouble + double.Parse(aExp[pos].ToString()) * Math.Pow(10, -l);
}
else
{
throw new Exception("It must be a true operation");
}
numStack.Push(tmpDouble);
tmpString += aExp[pos];
}
else
{
numStack.Push(int.Parse(aExp.Substring(pos, 1)));
}
pos++;
}
}
return numStack.Pop();// compute(numStack.Pop(), numStack.Pop(), opeStack.Pop());
}
private static void function(ref string aExp, string function)
{
string[] exp = aExp.Split(new char[] { '+', '-', '*', '/', '(', ')', ' ' }, StringSplitOptions.RemoveEmptyEntries);
int pos = aExp.IndexOf(function) + function.Length;
if (aExp[pos] == '(')
{
int countL = 1;
int countR = 0;
string tmp = "(";
for (pos = pos + 1; ; pos++)
{
if (countR == countL)
{
double value = MathF(function, Calculate(tmp));
aExp = aExp.Replace(function + tmp, value < 0 ? "(0" + value.ToString()+")" : value.ToString());
return;
}
else
{
tmp += aExp[pos];
if (aExp[pos] == ')')
{
countR++;
}
else if (aExp[pos] == '(')
{
countL++;
}
}
}
}
else
{
throw new Exception("It must be a true function");
}
}
private static double MathF(string fun, params object[] value)
{
fun = fun[0].ToString().ToUpper() + fun.Substring(1);
return (double)(typeof(Math).GetMethod(fun).Invoke(null, value));
}
private static bool isNum(char aChar)
{
char[] opeChars = { '+', '-', '*', '/', '(', ')', '#' };
if (Array.IndexOf(opeChars, aChar) >= 0)
{
return false;
}
if ((aChar < '0' || aChar > '9') && aChar != '.')
{
throw new Exception("It must be a true operation");
}
return true;
}
private static double compute(double d1, double d2, char aChar)
{
if (aChar == '*')
{
return d2 * d1;
}
if (aChar == '/')
{
if (d2 != 0)
{
return d2 / d1;
}
else
{
throw new Exception("The divisor is zero!");
}
}
if (aChar == '+')
{
return d2 + d1;
}
else
{
return d2 - d1;
}
}
private static char preOperator(char firstOpe, char secondOpe)
{
char[] addRank = { '+', '-' };
char[] multiRank = { '*', '/' };
if (Array.IndexOf(multiRank, firstOpe) >= 0 && Array.IndexOf(addRank, secondOpe) >= 0)
{
return '>';
}
if (secondOpe == '#')
{
return '>';
}
if (firstOpe == '#')
{
return '<';
}
if (firstOpe == '(')
{
return '>';
}
if (firstOpe == ')')
{
if (secondOpe == '(')
{
return '=';
}
else
{
return '<';
}
}
if (secondOpe == '(')
{
return '>';
}
return '<';
}
}
}
第2个回答 2008-12-16
可以去看下编译原理的书,方法是先把表达式转化成左式表示法,然后再来处理就简单多了
a+c -> +ac a+b*c -> +a*bc
a+b*c-d
转化成:
-+a*bcd
a*(b+c)/d
->
/*a+bcd