/// <summary>
/// 根据算术公式进行计算
/// </summary>
/// <param name="formula">string 类型的公式 如:sin(3*π-2cos(3*π-2))*2-sin(0.12*π) </param>
/// <returns></returns>
public static double formulaComput(string formula)
{
//先把常量变成数字
formula = formula.Replace("π", Math.PI.ToString());
formula = formula.Replace('(', '(').Replace(')', ')');
//预处理获取括号所在的index
List<ComputEntity> computEntities = new List<ComputEntity>();
List<string> rexs = new List<string> { "sin", "cos", "sinh", "cosh" };
foreach (var rex in rexs)
{
var matches = Regex.Matches(formula, rex + @"\(");
foreach (Match match in matches)
{
ComputEntity computEntity = new ComputEntity();
computEntity.beginBracketsIndex = match.Index + match.Length;
computEntity.beginIndex = match.Index;
computEntity.rex = rex;
computEntity.matchLength = match.Length;
computEntities.Add(computEntity);
}
}
//根据括号的所在处理sin ,cos 等函数,一定要先处理最后的那个,因为,这个很难解释
//仔细想想就知道了,就是这个理,从公式的最后处理到前面是正确的做法
foreach (var comput in computEntities.OrderByDescending(t => t.beginIndex))
{
string tempFormula = formula.Substring(comput.beginBracketsIndex, formula.Length - comput.beginBracketsIndex);
int leftBracketsCount = 0;
for (int i = 0; i < tempFormula.Length; i++)
{
if (tempFormula[i].Equals(')'))
{
if (leftBracketsCount == 0)
{
comput.lastIndex = comput.beginBracketsIndex + i;
comput.contentLengh = i;
comput.allLength = comput.matchLength + i + 1;
break;
}
else
{
leftBracketsCount--;
}
}
else if (tempFormula[i].Equals('('))
{
leftBracketsCount++;
}
}
var result = tableComput(formula.Substring(comput.beginBracketsIndex, comput.contentLengh));
//根据要计算的方法,进行计算
switch (comput.rex)
{
case "sin":
result = Math.Sin(result);
formula = formula.Replace(formula.Substring(comput.beginIndex, comput.allLength), result.ToString());
break;
case "cos":
result = Math.Cos(result);
formula = formula.Replace(formula.Substring(comput.beginIndex, comput.allLength), result.ToString());
break;
case "sinh":
result = Math.Sinh(result);
formula = formula.Replace(formula.Substring(comput.beginIndex, comput.allLength), result.ToString());
break;
case "cosh":
result = Math.Cosh(result);
formula = formula.Replace(formula.Substring(comput.beginIndex, comput.allLength), result.ToString());
break;
default:
break;
}
}
return tableComput(formula);
}
/// <summary>
/// 用table 这个库来进行计算
/// </summary>
/// <param name="formula"></param>
/// <returns></returns>
public static double tableComput(string formula)
{
DataTable dataTable = new DataTable();
Console.WriteLine(formula);
var result = dataTable.Compute(formula, "");
return Convert.ToDouble(result);
}
/// <summary>
/// 计算公式实体
/// </summary>
public class ComputEntity
{
public string rex;
public int matchLength;
public int beginIndex;
public int beginBracketsIndex;
public int lastIndex;
public int contentLengh;
public int allLength;
}