您的位置:首页 > 理论基础 > 数据结构算法

C#数学表达式计算(中缀转换后缀)数据结构 括号 四则运算 幂运算 取模 三角函数

2018-10-12 20:21 591 查看

前言:

1.遇到操作数,直接输出;
2.栈为空时,遇到运算符,入栈;
3.遇到左括号,将其入栈;
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出; (左括号丢弃 不输出)
5.遇到其他运算符 + - * / 时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;
6.最终将栈中的元素依次出栈,输出。
全文地址请点击:https://blog.csdn.net/qq_34992845/article/details/70313588?utm_source=copy

后缀表达式的计算:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

如何区分负号与减号
如果“-”是第一个字符时{
在前面加上“0-”

否则{
如果“-”前一个字符是数字 “-”是减号
如果“-”前一个字符是“^”幂运算符 “-”是负号
否则在前面加上“0-”

如-1-(-4^2)
会转换成0-1-(0-4^2)来处理

三角函数的运算思路(这里用的是角度制)
输入式子->转换成小写->转换成运算符->计算
如输入Sin(30)
转换成小写sin(30)
转换成运算符s(30)
运算0.5

代码:

若有不正之处,请多多谅解并欢迎指正。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 计算表达式
{
class Program
{
static void 错误检测(string s,double d) {
double a= Calculation(s);
Console.WriteLine(string.Format("{0}        计算结果{1}  正确结果{2}   ",s,a,d));
}

static void Main(string[] args)
{
/*
容易出错的式子:
-2*(5-2)=-6
-2*(-2)=4
1-(-4^2)=17
1+(-4^-2)=0.9375
1+(-4)^-2=1.0625

*/

错误检测("-2 * (5 - 2)" ,-6);
错误检测("-2*(-2)" , 4);
错误检测("-64*(-4)^(-2)" , -4);
错误检测("1-(-4^2)" , 17);
错误检测("-1+(-4^-2)" , -1.0625);
错误检测("1+(-4)^-2" , 1.0625);
错误检测("Sin(90)", 1);
错误检测("1-4*Sin(-1*(-2^5+2))", -1);
错误检测("8*sin(-1*(-2^5+2))^2", 2);
错误检测("cos60*4", 2);
错误检测("tan(44+1)", 1);
Console.WriteLine(string.Format("{0}        计算结果{1}  正确结果{2}   ", "tan(90)", Calculation("tan(90)"), "不存在的"));

//Console.WriteLine(Calculation("S(-30)"));

}
public static double Calculation(string str)//函数已封装好 用到的时候直接调用该方法ok
{
//Console.WriteLine("中缀表达式:"+str);
str=str.ToLower();//把字符串转换成小写
RemoveSpaces(ref str);
StrPreprocessing(ref str);
//Console.WriteLine("中缀表达式:" + str + " 预处理");

List<object> list = ToPostfix(str); //转换成中缀表达式
return CalculationPostfix(list);
}
static double CalculationPostfix(List<object>list)//计算后缀表达式
{
List<double> stacks = new List<double>();
//计算后缀表达式
for (int i = 0; i < list.Count; i++)
{
if (list[i] is double)
{
stacks.Add((double)list[i]);
}
else
{
string c = (string)list[i];
double aa, bb;
switch (c)
{
case "s":
aa = stacks.Last();
stacks.RemoveAt(stacks.Count - 1);
stacks.Add(Math.Sin(aa*Math.PI/180));//这里用的是角度制 弧度制的话改成Math.Sin(aa)就行了
break;
case "c":
aa = stacks.Last();
stacks.RemoveAt(stacks.Count - 1);
stacks.Add(Math.Cos(aa * Math.PI / 180));
break;
case "t":
aa = stacks.Last();
stacks.RemoveAt(stacks.Count - 1);
stacks.Add(Math.Tan(aa * Math.PI / 180));
break;
default:
bb = stacks.Last();
stacks.RemoveAt(stacks.Count - 1);
aa = stacks.Last();
stacks.RemoveAt(stacks.Count - 1);
stacks.Add(Operation(aa, bb, c));
break;
}
}
}
return stacks[0];//返回计算结果
}
static List<object> ToPostfix(string infix)//转换成后缀表达式
{
List<object> list = new List<object>();//一个集合
List<string> stacks = new List<string>();//用来存符号的栈
int len = infix.Length;
int a = 0, b = 0;
for (int i = 0; i < len; i++)
{
//该for循环作用是 把字符串的数字括号运算符区分开来并添加到集合list
string c = infix.Substring(i, 1);
if (IsNum(c))
{
b++;
if (i == len - 1) list.Add(ParseNum(infix.Substring(a, b)));
}
else
{
string sum = infix.Substring(a, b);
if (sum.Length != 0) list.Add(ParseNum(sum));
a = i + 1;
b = 0;
}
switch (c) //符号栈操作
{
case "(": stacks.Add(c); break;
case ")":
while (stacks.Count > 0)
{
if (stacks.Last() != "(")
{
list.Add(stacks.Last());
stacks.RemoveAt(stacks.Count - 1);
}
else
{
stacks.RemoveAt(stacks.Count - 1);
break;
}
}
break;
case "+":
case "-":
case "*":
case "/":
case "%":
case "^":
case "s":
case "c":
case "t":
while (stacks.Count > 0)
{
if (Priority(c, stacks.Last()))
{
list.Add(stacks.Last());
stacks.RemoveAt(stacks.Count - 1);
}
else break;
}
stacks.Add(c);
break;
}

}
while (stacks.Count > 0) //最后的出栈
{
list.Add(stacks.Last());
stacks.RemoveAt(stacks.Count - 1);
}
//Console.Write("后缀表达式:");
//for (int i = 0; i < list.Count; i++) Console.Write(list[i]);
return list;
}
static void StrPreprocessing(ref string infix)//字符串预处理
{
int len = infix.Length;
StringBuilder str = new StringBuilder();

//把sin cos tan分别改为s c t方便后面的运算
while (infix.IndexOf("sin") >=0 || infix.IndexOf("cos") >=0 || infix.IndexOf("tan") >=0)
{
int a = infix.IndexOf("sin");
if(a!=-1) infix=infix.Remove(a+1,2);
a = infix.IndexOf("cos");
if (a != -1) infix=infix.Remove(a + 1, 2);
a = infix.IndexOf("tan");
if (a != -1) infix=infix.Remove(a + 1, 2);
}

len = infix.Length;
str = new StringBuilder();
for (int i = 0; i < len; i++)
{
string c = infix.Substring(i, 1);
if (c == "-")
{
if (i == 0)
{
str.Append("0-");
}
else
{
string cc = infix.Substring(i - 1, 1);
if (IsNum(cc))
{
str.Append(c);
}
else if (cc == "^")
{ //避免2^-2=0.25转换成2^0-2=-1
str.Append("_");
}
else
{
// str+="_";
str.Append("0-");
}
}
}
else str.Append(c);
}
infix = str.ToString();

}
static void RemoveSpaces(ref string infix)//删除空格
{
int len = infix.Length;
StringBuilder str = new StringBuilder();//https://blog.csdn.net/qq_28187979/article/details/76607253
//删除空格
for (int i = 0; i < len; i++)
{
string c = infix.Substring(i, 1);
if (c == " ") continue;
str.Append(c);
}
infix = str.ToString();
}
static double Operation(double a,double b,object c)//运算
{
switch (c)
{
case "+": return a + b;
case "-": return a - b;
case "*": return a * b;
case "/": return a / b;
case "%": return a % b;
case "^": return Math.Pow(a, b);
}
throw new Exception();
}
static bool Priority(string a,string b)//优先级判断
{
//true为a优低于b
if (Grade(a) <= Grade(b)) return true;
return false;
}
static int Grade(string s)//返回该运算符的等级
{
switch (s)
{
case "(": return 0;
case "-":
case "+": return 1;
case "/":
case "*":
case "%": return 2;
case "^": return 3;
case "s":
case "c":
case "t": return 4;
case ")": return 5;
}
return -1;
}
static bool IsNum(string s)//传入一个字符 判断该字符是不是数字。负号和点也属于数字 -3.14
{
switch (s)
{
case "_"://预处理之后负号(-)转换成_  减号-不变
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
case ".": return true;
}
return false;
}
static bool IsSymbol(object s)//传入一个字符 判断该字符是不是符号
{
switch (s)
{
case "+":
case "-":
case "*":
case "/":
case "%":
case "^":
case "s":
case "c":
case "t":
return true;
}
return false;
}
static double ParseNum(string num)//string转换double 在double.Parse(str);的基础上处理
{
if (num.Length > 0)
{
if (num.Substring(0, 1) == "_") return -double.Parse(num.Substring(1, num.Length - 1));
else return double.Parse(num.Substring(0, num.Length));
}
throw new Exception();
}
}
}
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐