四则运算的解析

怎样将字符串的算数表达式计算出来?

如果使用正则表达式来匹配,有点不怎么好想,而且一般想法设计到递归,而在Python中是非常不建议使用递归的,

因为它不仅有递归深度的限制(一般是1000个栈帧),而且不支持尾递归优化。

最简单的办法就是先将表达式转化为前缀表达式,然后通过前缀表达式来计算出结果。

前缀表达式(运算符中前面)也被称为波兰式,相应的后缀表达式(运算符中后面)也被成为逆波兰式,而我们生活中,还有

常见的大多数编程语言中使用的都是中缀表达式。

中缀表达式转化为前缀表达式规则:

  (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;

  (2) 从右至左扫描中缀表达式

  (3) 遇到操作数时,将其压入S2

  (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:

  (4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈

  (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1

  (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,

  再次转到(4-1)与S1中新的栈顶运算符相比较

  (5) 遇到括号时:

  (5-1) 如果是右括号“)”,则直接压入S1

  (5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,

  此时将这一对括号丢弃

  (6) 重复步骤(2)至(5),直到表达式的最左边

  (7) 将S1中剩余的运算符依次弹出并压入S2

  (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。

使用前缀表达式来计算最大特点就是它去掉了括号。

将中缀表达式转化为前缀表达式

def mid_to_prev(expressions: str):
    priority = {  # 运算符的优先级
        "/": 1,
        "//": 1,
        "*": 1,
        "%": 1,
        "+": 0,
        "-": 0,
        "**": 2 }
    expression_list = expressions.split() #
    number_stack = [] # 数字栈
    symbol_stack = [] # 运算符栈
    for x in expression_list[::-1]:
        if x.isdigit():
            number_stack.insert(0, x)  # 如果是整数直接存进去
        else:
            if x == ‘(‘:         # 如果是 ( 弹出运算符栈中的运算符直到遇到 (
                pop_symbol = symbol_stack[0]
                while pop_symbol != ‘)‘:
                    pop_symbol = symbol_stack.pop(0)
                    number_stack.insert(0, pop_symbol)
                    pop_symbol = symbol_stack[0]
                else:
                    symbol_stack.pop(0)
            elif len(symbol_stack) == 0 or symbol_stack[0] == ‘)‘ or x == ‘)‘ or priority[x] >= priority[symbol_stack[0]]:
                symbol_stack.insert(0, x)  # 当符号栈为空 或者 遇到 ) 或者栈顶的符号是 ) 或者优先级大于等于符号栈顶的运算符优先级 直接存进去

            elif priority[x] < priority[symbol_stack[0]]:  # 优先级小于符号栈顶元素的时候
                while symbol_stack[0] != ‘)‘ and priority[x] < priority[symbol_stack[0]]:
                    number_stack.insert(0, symbol_stack.pop(0))
                else:
                    symbol_stack.insert(0, x)
    else:
        while len(symbol_stack) != 0:
            number_stack.insert(0, symbol_stack.pop(0))
    return number_stack

例子:

将转化到的前缀表达式栈进行运算就简单了

def calc(number1,number2,calc): # 两个数运算
    if calc == ‘/‘:
        return number1 / number2
    elif calc == ‘*‘:
        return number1 * number2
    elif calc == ‘//‘:
        return number1 // number2
    elif calc == ‘**‘:
        return number1 ** number2
    elif calc == ‘%‘:
        return number1 % number2
    elif calc == ‘+‘:
        return number1 + number2
    elif calc == ‘-‘:
        return number1 - number2

得到总的结果:

def operation(stack_list:list):
    number = []
    for x in stack_list[::-1]:
        if x.isdigit():
            number.insert(0, x)
        else:
            first = number.pop(0)
            second = number.pop(0)
            tmp = calc(int(first),int(second), x)
            number.insert(0,tmp)
    return number.pop(0)

实例:

前面的前缀表达式结果:

经验证结果是正确的。

时间: 2024-10-30 14:54:49

四则运算的解析的相关文章

四则运算脚本解析计算

四则运算脚本解析计算 1.个位数的加减法运算 记住前一位的加号或减号运算符,使用加号或减号用运算符后面的数字改变累加值. package yuki.arithmetic.script; public class SingleDigitTest { public static void main(String[] args) { String s1 = "1+2+3+4+5+6+7+8+9"; System.out.println(s1 + "=" + calcula

四则运算表达式解析和求值(支持括号、小数、小数正负号)

需求分析 四则运算表达式的解析和求值从概念上看是一个逻辑很清晰的过程. 遵循了左结合.优先级差异和括号可以提升优先级这三条规则. 实现思路 实际上只要遍历表达式,将小数和运算符分离到两个序列容器中,在遍历的过程中,考虑左结合和括号对优先级的影响,将相关信息和运算符记录在一起,然后在遍历结束后,按照优先顺序从高到底,从小数序列中拉取两个元素(可能是中间结果的二叉树,实际上小数是一种特例,是左右子树为空的解析完成的二叉树),并且把运算符的两棵子树指向两个元素,把这棵新树放回到小数容器中.不断重复这个

QT之计算器对四则运算表达式的解析

前面我们已经关于计算器介绍的已经够多了,那么它现在还是没有具备计算的功能. 今天我们来继续讲解计算器的解析算法,那么对于一个四则运算表达式, 它是如何读懂的呢?比如:"+9.11 + ( -3 - 1 ) * -5 ": 人类习惯的数学表达式叫做中缀表达式,还有一种将运算符放在数字后面的后缀表达式, 比如:5 + 3 ==> 5 3 +: 1 + 2 * 3 ==> 1 2 3 * +;像这种就是后缀表达式. 那么中缀表达式是符合人类的阅读和思维习惯,后缀表达式则符合计算机

四则运算小题目解析

小题目四则运算下面是源代码 #include <iostream> using namespace std; void main() {  int X0[1000],Y0[1000],Z0[1000],X1[1000],Y1[1000],Z1[1000],X2[1000],Y2[1000],Z2[1000],X3[1000],Y3[1000],Z3[1000],A[1000],a,b,c;  int i,j,A0,A1,A2,A3,B0,B1,B2,B3;  int number1,numbe

个人项目——四则运算生成器和解析器

1.预计耗费时间 vs 实际耗费时间 预计: PSP2.1 Personal Software Process Stages Time Planning 计划 · Estimate · 估计这个任务需要多少时间 2days Development 开发 · Analysis · 需求分析 (包括学习新技术) 1days · Design Spec · 生成设计文档 30min · Design Review · 设计复审 (和同事审核设计文档) 10min · Coding Standard ·

软件工程附加篇章:进阶四则运算和Core对接

0x01 :计算模块(Core)和前端对接 首先特别结对编程刘乾组(SivilTaram)提供的计算模块(Core),http://www.cnblogs.com/SivilTaram/p/4859934.html 在Core模块的说明文档中,我们可以清晰发现在计算模块Core主要实现了表达式计算.四则运算表达式生成.题目文件和答案文件的审核的功能: 但在设计思路上:          在整体的设计思路上,SivilTaram组的Core模块同样将写入和读取文件的逻辑封装在计算模块中:但在自己的

软件工程项目之二:结对编程——四则运算生成计算程序

0x01 :简介 本次的编程任务是完成一个具有UI界面的,具备四则运算生成.计算.判断对错功能的程序.本次程序使用C#语言编写,用时为2周. 0x02 :软件工程和PSP表格记录 PSP 2.1 Persinal Software Process Stages Time(Estimated) Time(Real) Planning 计划     Estimate 估计这个任务需要多少时间 24h 36h Development 开发     Analysis 需求分析(包括学习新技术) 8~10

软件工程启程篇章:C#和四则运算生成与运算

0x01 :序言 I leave uncultivated today, was precisely yestoday perishes tomorrow which the person of the body implored “看不清楚的时光印痕,像是泛黄的底片,明明还记得那个故事,却忘了故事里的风月”,不知如今因为生成规则.词法排序或效率而争执地面红耳赤的少年们,多少岁月走过重新翻阅看着七零八落的注释和代码段,是否只得慨叹岁月这把最锋利的杀猪刀,然而,即便最终能停留在代码段的注释行不过寥

【week2】结对编程-四则运算 及感想

首先我要说一下,我得作业我尽力了,但是能力有限,还需练习. 四则运算,改进代码流程: 1.手动输入算式(属于中缀表达式) 2.将中缀表达式转化成后缀表达式 生成out数组 3.一个操作数栈,一个运算符栈,按照后缀表达式计算方法将out中的字符分别放入两个栈 4.当操作数栈只有一个数时结束计算. 代码分段解析如下: 中缀变后缀: public List<String> SolveOrder(String[] in,HashMap<String,Integer>precedence){