当前位置:首页 > Windows程序 > 正文

c# 逆波兰式实现计算器

2024-03-31 Windows程序

语文不好,不太会组织语言,希望不要太在意。

如题,先简要介绍一下什么是逆波兰式  通常我们在写数学公式的时候  就是a+b+c这样,这种表达式称为中缀表达式,逆波兰式又称为后缀表达式,例如a+b 后缀表达式就为ab+

而把中缀表达式转为逆波兰式也是很容易的,以下算法摘自百度百科

简要说一下栈,栈是一种先进后出的对象集合,可以把栈理解为一个桶,先进后出  Stack   Peek()是取出但是不剔除 做比较的时候用,Pop()是出栈,Push()入栈

首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为输入逆波兰式的栈S2(空栈),S1栈可先放入优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:

(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2栈

(2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送入S1栈。

(3)若取出的字符是“(”,则直接送入S1栈顶。

(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。

(5)重复上面的1~4步,直至处理完所有的输入字符

(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。

完成以上步骤,S2栈便为逆波兰式输出结果。不过S2应做一下逆序处理。便可以按照逆波兰式的计算方法计算了!把一个表达式转为逆波兰式  比如 (a+b)*c 逆波兰式为ab+c*

a为数字,入栈,b为数字,入栈,“+”,为运算符  a b出栈,计算a+b 然后将结果 入栈,c入栈,"*"为运算符,a+b的结果出栈,c出栈,运算 * 将结果再入栈 运算完毕,栈里的结果就是我们想要的了

 

代码实现(有点乱)

 

判断元素是不是为数字

static bool IsNumber(string s) { return Regex.IsMatch(s, @"\d+"); }

判断元素是否为运算符(+-*/)

static bool IsSiZe(string s) { string ts = "+-*/"; return ts.IndexOf(s) > -1; }

判断优先级

static int Level(string s) { int i = 0; switch (s) { case ",": i = 0; break; case "(": case ")": case "#": i = 1; break; case "+": case "-": i = 2; break; case "*": case "/": i = 3; break; } return i; }

计算

private static void Calc(Stack<string> numStack, Stack<string> operStack) { int rightnum = int.Parse(numStack.Pop()); int leftnum = int.Parse(numStack.Pop()); string oper = operStack.Pop(); switch (oper) { case "+": numStack.Push((leftnum + rightnum).ToString()); break; case "-": numStack.Push((leftnum - rightnum).ToString()); break; case "*": numStack.Push((leftnum * rightnum).ToString()); break; case "/": numStack.Push((leftnum / rightnum).ToString()); break; } }

总体实现代码

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/43021.html

Jm-杰米博客Jamie
草根站长的技术交流乐园!IT不会不要紧快来好好学习吧!
  • 20786文章总数
  • 7494595访问次数
  • 3366建站天数
  • 友情链接