Python入门(八)——计算器作业:初级版,正则表达式(RE)初级应用

终于调了半天bug完成一版,但是与win10自带的计算器有差值,明天在搞
在这里插入图片描述
在这里插入图片描述

# Author:AD
# Date:2020/2/27
'''
开发一个简单的python计算器

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


hint:

re.search(r'\([^()]+\)',s).group()

'(-40/5)'
'''
#!/usr/bin/env Python
# coding=utf-8
import re

# 利用re编译通用去字符的规则空格,括号
delet = re.compile('[' ', \( ,  \)]')


# 功能:加减运算,
# 输入:字符串(有可能带括号,空格,++,-+,+-、--都删除)
# 输出:数字(string)
# 测试案例:(--4.5 + 5.4)、4  +5、-+3-6、-3-4
def add_sub(str_input):
    str_input = delet.sub('', str_input)  #移除空格和括号
    str_input = re.sub('(\+-)|(-\+)', '-', str_input) #将-+  +-  换为 -可行的方式之一
    # str = re.sub('[+\-,\-+)]', '-', str) #不行的方式之一
    str_input = re.sub('(\+\+)|(--)', '+', str_input) #将++ -- 换为+
    str_num = re.split('[ \-, +]', str_input)  # 将数放在一个列表中
    if '' in str_num:
        str_num.remove('') #开头有 - 的话会产生一个空元素,将其移除
    str_sign = re.findall('[+, \-]', str_input) #存入符号
    if len(str_sign) != len(str_num): #为了后面计算一致性,如果前面没有符号增加正号
        str_sign.insert(0, '+')

    i = 0 #统计数据列表元素用的次数
    sum = 0 #统计最后的和
    for s in str_sign:
        if s == '+':
            sum += float(str_num[i])
            i += 1
        else:
            sum -= float(str_num[i])
            i += 1
    return str(sum)

'''
功能:实现乘除功能
输入:带括号的乘除表达式(可能含有空格、( 、)带正负号)
输出:计算完成的字符串
'''
def multi_divi(str_input):
    str_input = delet.sub('', str_input)  #移除空格和括号
    num_negative = len(re.findall('-', str_input)) #将负号个数取出,为判断最终正负使用 防止有-4*(-5)的情况
    str_input = str_input.replace('-', '') #去掉符号,为后面计算做准备
    str_num = re.split('[*, /]', str_input) #按照乘除将其分开为数的列表
    if '' in str_num:
        str_num.remove('')  # 开头有  的话会产生一个空元素,将其移除
    str_sign = re.findall('[*, /]', str_input)  # 存入符号
    sum = 0.0 #记录结果
    i = 1 #记录数列表用的次数,从1开始循环,符号肯定比数少一个
    sum = float(str_num[0])
    while i < len(str_num):
        if str_sign[i-1] == '/':
            sum /= float(str_num[i])
            i += 1
        else:
            sum *= float(str_num[i])
            i += 1
    if num_negative % 2 == 0:
        return str(sum)
    else:
        return  str(-sum)


'''
功能:处理一个括号单元的内容
输入:不包含括号的最底层运算式子
输出:计算结果(str)
'''
def calculate_brackets(str_input):
    str_input = delet.sub('', str_input)
    str_input = re.sub('(\+-)|(-\+)', '-', str_input)  # 将-+  +-  换为 -可行的方式之一
    str_input = re.sub('(\+\+)|(--)', '+', str_input)  # 将++ -- 换为+
    ismulti_divi = ('*' in str_input) or ('/' in str_input)
    isadd_sub = ('+' in str_input[1:]) or ('-' in str_input[1:])
    if ismulti_divi and isadd_sub:
        lst_multi_divi = re.split('[+, \-]', str_input)
        if '' in lst_multi_divi: #移除空格
            lst_multi_divi.remove('')
        lst_multi_divi_sign = re.findall('[+, \-]', str_input) #拼接结果使用
        if len(lst_multi_divi_sign) != len(lst_multi_divi):  # 为了后面计算一致性,如果前面没有符号增加正号
            lst_multi_divi_sign.insert(0, '+')
        sum = ''  # 记录最终结果
        i = 0 #记录次数拼接符号
        for mult in lst_multi_divi:
            sum = ''.join([sum, lst_multi_divi_sign[i], multi_divi(mult)])
            i += 1
        return add_sub(sum)
    elif ismulti_divi:
        return multi_divi(str_input)
    else:
        return add_sub(str_input)


def main():
    str_input = input('please input what to calculate:\n>>>')
    #str_input =  '1 - 2 * ((60 - 30 + (-40 / 5) * (9 - 2 * 5 / 3 + 7 / 3 * 99 / 4 * 2998 + 10 * 568 / 14)) - (-4 * 3) / (16 - 3 * 2))'
    #'1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
    str_input = re.sub(' ', '', str_input)
    str_input = re.sub('(', '(', str_input)
    str_input = re.sub(')', ')', str_input)
    while '(' in str_input:
        str_cal = re.findall('\([^(,)]*\)', str_input)
        for i in str_cal:
            str_input = str_input.replace(i, calculate_brackets(i))
    return calculate_brackets(str_input)

if __name__ == '__main__':
    print(main())

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值