已知一个 字符串表达式【四则运算】,求出 加减乘除 以及小括号的运算结果。
在控制台应用程序中,新建一个类 ArithmeticUtil.cs。详细代码与逻辑注释如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestLinq
{
/// <summary>
/// 四则算术运算【小括号、加减乘除】
/// </summary>
public class ArithmeticUtil
{
/*
* 已知一个 字符串表达式,求出 加减乘除 以及小括号的运算结果。
* string s="(3+5.2)*8-100/20+5.8*((2+3)*4)";
*/
/// <summary>
/// 计算含有小括号表达式的结果
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
public static double CalculateResult(string expression)
{
//先计算出小括号表达式,并去除所有的小括号
Stack<int> stackLeftBrackets = new Stack<int>();//左括号索引
while (expression.Contains(")")) //如果存在小括号,就计算出结果后 逐个去除
{
stackLeftBrackets.Clear();
for (int index = 0; index < expression.Length; index++)
{
if (expression[index] == '(')
{
stackLeftBrackets.Push(index);
}
else if (expression[index] == ')')
{
//stackRightBrackets.Push(i);
//遇到右括号时,找出最近的左括号
if (stackLeftBrackets.Count == 0)
{
Console.WriteLine("表达式非法,小括号不是成对出现的【存在右括号,没有找到对应的左括号】");
return 0;
}
int leftIndex = stackLeftBrackets.Pop();
string subExpression = expression.Substring(leftIndex + 1, index - leftIndex - 1);
double innerResult = CalculateWithoutBrackets(subExpression);
//字符串计算出结果后,去除一个小括号后,重新赋值
expression = expression.Substring(0, leftIndex) + innerResult + expression.Substring(index + 1);
//Console.WriteLine(expression);
break;
}
}
}
if (stackLeftBrackets.Count > 0)
{
Console.WriteLine("表达式非法,小括号不是成对出现的【存在左括号,没有找到右括号】");
return 0;
}
//此时,表达式中所有的小括号都已经计算完毕,无小括号。只用运行四则运算即可。
double result = CalculateWithoutBrackets(expression);
return result;
}
/// <summary>
/// 没有括号的四则运算 加减乘除
/// </summary>
/// <param name="subExpression"></param>
/// <returns></returns>
public static double CalculateWithoutBrackets(string subExpression)
{
//表达式形如:4.5+2*6.9-13.8/5+6
string str = "";
List<double> listNumber = new List<double>();
List<char> listOper = new List<char>();
for (int index = 0; index < subExpression.Length; index++)
{
if (subExpression[index] == '+' || subExpression[index] == '-' || subExpression[index] == '*' || subExpression[index] == '/')
{
listNumber.Add(double.Parse(str));
str = "";
listOper.Add(subExpression[index]);
}
else
{
str = str + subExpression[index];
}
}
//最后 还要将最后一个数字放入链表
listNumber.Add(double.Parse(str));
//收集所有的运算符到集合listOper,收集所有的数字到集合listNumber。其中listNumber的个数比listOper的个数多一个
//Console.WriteLine(string.Join("||",listNumber));
//Console.WriteLine(string.Join("||", listOper));
//先乘除,过滤出乘除符号,计算出最新结果后,删除该乘除符号
for (int i = 0; i < listOper.Count; i++)
{
if (listOper[i] == '*' || listOper[i] == '/')
{
double first = listNumber[i];
double second = listNumber[i+1];
double tempResult = 0;
if (listOper[i] == '*')
{
tempResult = first * second;
}
else
{
tempResult = first / second;
}
//Console.WriteLine("乘除结果:" + tempResult);
//计算出 乘(除)号两边的结果,从集合中移除 【乘(除)号右边的数】。同时将算术结果重新赋值给 【乘(除)号左边的数】
listNumber[i] = tempResult;
listNumber.RemoveAt(i + 1);
listOper.RemoveAt(i);
i--;
}
}
//Console.WriteLine(string.Join("||", listNumber));
//Console.WriteLine(string.Join("||", listOper));
//现在只有加减操作,依次从左到右计算即可
for (int i = 0; i < listOper.Count; i++)
{
double first = listNumber[i];
double second = listNumber[i + 1];
double tempResult = 0;
if (listOper[i] == '+')
{
tempResult = first + second;
}
else
{
tempResult = first - second;
}
//Console.WriteLine("加减结果:" + tempResult);
//计算出 乘(除)号两边的结果,从集合中移除 【乘(除)号右边的数】。同时将算术结果重新赋值给 【乘(除)号左边的数】
listNumber[i] = tempResult;
listNumber.RemoveAt(i + 1);
listOper.RemoveAt(i);
i--;
}
//最后的结果 listNumber只留下一个元素,也就是计算结果。listOper元素为空
//Console.WriteLine(string.Join("||", listNumber));
//Console.WriteLine(string.Join("||", listOper) == "");
return listNumber.Count > 0 ? listNumber[0] : 0;
}
}
}
在默认的Program.cs的Main函数下 输入测试代码:
string exp = "4.5+2*6.9-13.8/5+6";
double calResult = ArithmeticUtil.CalculateResult(exp);
Console.WriteLine("{0}={1}", exp, calResult);
exp = "(3+5.2)*8-100/20+5.8*((2+3)*4)";
calResult = ArithmeticUtil.CalculateResult(exp);
Console.WriteLine("{0}={1}", exp, calResult);
Console.ReadLine();