summer-han

要求:

1、实现加减乘除及拓号优先级解析

2、用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致

 

思路:

1、定义正负的乘除法运算

2、定义计算的优先级

3、将复杂运算括号中的算式优先计算,运算结果合并入算式中,最后将算式变成简单的加减乘除运算再计算结果

 流程图:

                                                              

 

code:

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author:summer_han

import re
import sys


def mult_div(l,x):
    \'\'\'
    定义最小 乘法和除法单元 并计算后 只剩下 加减法 ,l 为 正则转换后的 list, x 代表 * 或者 /
    :param l:
    :param x:
    :return:
    \'\'\'
    p = l.index(x)
    # print(p,l)
    # 定义 x 为 * 时 x 的下一位 是否为 -,如果 为 - 则 为负数
    if x == \'*\' and l[p+1] != "-":
        r = float(l[p-1]) * float(l[p+1])
    elif x == \'*\' and l[p+1] == "-":
        r = -(float(l[p-1]) * float(l[p+2]))
    # 定义 x 为 / 时 x 的下一位 是否为 -,如果 为 - 则 为负数
    elif x == \'/\' and l[p+1] != "-":
        r = float(l[p-1]) / float(l[p+1])
    elif x == \'/\' and l[p+1] == "-":
        r = -(float(l[p-1]) / float(l[p+2]))

    # 三个位置 计算后 ,删除 3个位置的元素
    del l[p-1],l[p-1],l[p-1]
    # 将 计算结果插入到删除位置
    l.insert(p-1,str(r))


def func(exps):
    \'\'\'
    函数计算主体,负责计算 只有加减乘除的运算
    :param exps:算式参数
    :return:返回计算结果
    \'\'\'
    rel=re.findall(\'([\d\.]+|/|-|\+|\*)\',exps)
    # print("打印初始列表",rel)
    # 当rel为真时
    while True:
        #  既有乘法又有除法运算符时,判断乘除法运算符位置,位置小的优先计算
        if \'*\' in rel and \'/\' in rel:
            pos_A = rel.index(\'*\')
            pos_B = rel.index(\'/\')
            #  判断 乘除法运算符 位置
            if pos_A < pos_B:
                mult_div(rel,\'*\')
                # print(rel) # 打印rel 对比 list
            else:
                mult_div(rel,\'/\')
        #  只有 乘法 没有 除法
        elif \'*\' in rel and \'/\' not in rel:
            mult_div(rel,\'*\')
        # 只有 除法 没有 乘法
        elif \'*\' not in rel and \'/\' in rel:
            mult_div(rel,\'/\')

        else:
            #  初始化 运算结果为 0
            sum = 0
            #  判断列表第一个元素是否为 \'-\' 如果为 \'-\' 则合并 前两个元素,并且删除第二个元素 rel[1],保留合并后的元素
            if rel[0] == \'-\':
                rel[0] = rel[0] + rel[1]
                # 删除合并后的无用 元素
                del rel[1]
                # 打印结果查看列表元素是否正确
                # print(rel)
            #  初始化运算结果 为列表第一个元素的值
            sum += float(rel[0])
            # print(\'---------------\',sum)

            #  判断元素符号,范围为1到列表最大长度,步长为2
            for i in  range(1,len(rel),2):
                #  打印 符号 (+ -)
                # print(rel[i])

                # 判断 + 后后面是否是\'-\',如果不是\'-\' 则 sum结果为 加下一位
                if rel[i] == \'+\' and rel[i+1] != \'-\':
                    sum += float(rel[i+1])
                # 判断 + 后面是否为 \'-\',如果是\'-\',则 sum 结果为 - i+2位 (i+1位是\'-\')
                elif rel[i] == \'+\' and rel[i+1] == \'-\':
                    sum -= float(rel[i+2])
                # 判断 - 后后面是否是\'-\',如果不是\'-\' 则 sum结果为 减下一位
                elif rel[i] == \'-\' and rel[i+1] != \'-\':
                    sum -= float(rel[i+1])
                # 判断 - 后后面是否是\'-\',如果是\'-\' 则 sum结果为 加下一位
                elif rel[i] == \'-\' and rel[i+1] == \'-\':
                    sum += float(rel[i+2])
            # print(sum)
            return sum

# expression = \'-100.5+40*5/2-3*2*2/4+9\'
def calculate(exps):
    \'\'\'
    负责算式的分解,循环将()内的算式计算,最后将结果变成加减乘除运算在计算出结果
    :param exps:用户输入的算式
    :return:算式结果
    \'\'\'
    #定义提取 括号类元素的临时列表
    tmpex = []
    rlt = 0
    if \'(\' not in exps:
        rlt = func(exps)
        # print(rlt)
        return rlt

    else:
        # len(exps) 长度 从 0 开始
        for i in range(len(exps)):
            if exps[i] == \'(\':
                tmpex.append(i)
                # print("\033[41;1m ( 的位置:\033[0m",tmpex)
            elif exps[i] == \')\':
                # print("\033[35;1m括号取值位置判断:\033[0m",(tmpex[len(tmpex)-1])+1,i)

                # len(tmpex) 长度, len(tmpex)-1 为列表tmpex最后一个元素,因为从0开始计算第一个元素;
                # (tmpex[len(tmpex)-1])+1 为最后一个元素\'(\'下一位的位置,在 exps 中取值,i为第一个出现的\')\'

                subexpr = exps[tmpex[len(tmpex)-1]+1:i]  # 19-26
                # print("\033[42;1m子运算式\033[0m",subexpr)
                temp=func(subexpr)
                # print("\033[43;1m 存放临时结果 \033[0m",temp)
                # 初始化 exps 列表
                # len(tmpex-1) 为tmpex长度的最后一个元素 在exps 中 0到最后一个元素 )的位置,不取 )
                # 和 第一个最内层()的字运算结果 str(temp)合并,在和exps的[i+1]位到最后一个元素合并
                # 作为新的 exps ,以此类推循环 ,每次循环计算 str(temp)的值
                exps = exps[0:tmpex[len(tmpex)-1]]+str(temp)+exps[i+1:]
                #  删除tmpex中最后一个元素
                tmpex.pop()
                return calculate(exps)

if __name__ == \'__main__\':
    while True:
        exps = input("\033[31;1m请输入您的要计算的算式:\033[0m")
        print("\033[35;1mcalculate程序运行计算结果为:%s \neval执行结果为:%s\033[0m"%(calculate(exps),eval(exps)))

        flag = input("按【q】退出程序,或者按任意键继续:")
        if flag == \'q\':
            sys.exit("\033[42;1mExit the calculate program,Bye!\033[0m".center(50,\'-\'))
        else:
            continue

# exps = \'2+10-((6-3)*2+(5-2)*3)\'
# exps = \'-100.5+40*5/2-3*2*2/4+9\'
# exps = \'1 - 2 * ( (60-30 +(-40/5+3) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )\'
View Code

 

分类:

技术点:

相关文章: