正则的使用——编写一个简易的计算器

在 Alex 的博客上看到的对正则这一章节作业是编写一个计算器,要求能计算出下面的算式。

1 - 2 * ( (60-30 +(-40/5) * (9-25/3 + 7 /399/42998 +10 * 568/14 )) - (-43)/ (16-3*2) )

第一次编写计算器,为了理清逻辑,先编写一个 比较初级的版本,暂时只支持加减乘除。
分析上面的计算式,虽然只有加减乘除,但是还是比较复杂的运算,上面的计算式基本上是涵盖了所有加减乘除能遇到的所有情况。
我们先设一个计算器程序能达到的效果,运行程序时,程序要求用户输入一个计算式,然后程序计算结束后,返回一个值,也就是计算式最后的值。

程序比较关键的几点:
1.初步判断和处理用户提供的字符串,判断是否是正确的算式,其中包括,算式中是否出现了英文字母,左括号和右括号是否相等,去掉字符串中的空格,更复杂的判断先暂时不做。

2.计算顺序,由于计算是有优先级的,如果人工算,第一步就是去找最里层的括号,将最里层的括号的值在代出来计算运算。那么程序第一步就是判断计算式中是否有括号,如果有括号,就找到最里层的扩号,计算完后,就用得到的值来替换最里层的括号,得到一个新的字符串,在返回继续判断是否有括号,再计算,如此循环得到最后的值。

3.那么怎么来让程序来识别哪一个括号才是最里层的括号呢?由于正则默认的是贪婪匹配,找到最外层扩号很容易,找到最里层的反而不是太容易。换个思路,只要不是最里层的括号,那么这个括号里面一定还有括号,所以最里层的括号有一个特点,就是里面不再会有其他括号了。故正则可以这样写 '(([^()]+))' 。(这是这个程序实现的最关键的一点)

4 . 程序不完善之处,这个程序只支持加减乘除四则运算,功能还不够完善;由于python 自身的原因,在计算浮点数上,有时会出现不准确的情况,这个还需要在完善一下;为了方便处理,我是将所有的数字都转化为浮点数处理,故一些整数间的运算得到的结果也会是一个浮点数,还需要继续完善。
附上代码:

import re

x = input('请输入你要计算的计算式:')   # 用户输入
# 判断用户输入的是否有字母,括号个数是否正确,同时处理字符串中的空格

if re.findall('[a-zA-Z]',x):
    print('输入错误,算式中出现字母!')
    exit()
if '(' in x or ')' in x:
    if x.count('(') != x.count(')'):
        print('输入错误,括号个数不正确!')
        exit()
if ' ' in x:
    x = x.replace(' ','')

# 定义一个处理乘法和除法的函数,在只有加减乘除的运算中,除法若是最优先运算的话,不会出错。
# 经过这个函数处理后,计算式中的 乘除法就处理完了,只剩下加减法了
def multiplication_division(calculate):
    # 在计算完括号里面的计算式时,如果得到一个负数,那么替换后会出现 '*-' '/-' '+-' '--' 这么几种情况,故函数先判断处理这种情况。
    while '*-' in calculate:                    
        if re.search('-[0-9.]+\*-',calculate):
            replace1 = re.search('-[0-9.]+\*-',calculate).group()
            replace = replace1.replace('*-','*')
            replace = replace.replace('-','+')
            calculate = calculate.replace(replace1,replace)
        elif re.search('\+[0-9.]+\*-',calculate):
            replace1 = re.search('\+[0-9.]+\*-', calculate).group()
            replace = replace1.replace('*-', '*')
            replace = replace.replace('+', '-')
            calculate = calculate.replace(replace1, replace)
    while '/-' in calculate:
        if re.search('-[0-9.]+/-',calculate):
            replace1 = re.search('-[0-9.]+/-',calculate).group()
            replace = replace1.replace('/-','/')
            replace = replace.replace('-','+')
            calculate = calculate.replace(replace1,replace)
        elif re.search('\+[0-9.]+/-',calculate):
            replace1 = re.search('\+[0-9.]+/-', calculate).group()
            replace = replace1.replace('/-', '/')
            replace = replace.replace('+', '-')
            calculate = calculate.replace(replace1, replace)
    while '/' in calculate:
        if re.findall('^-[0-9.]+/[0-9.]+',calculate):
            division = re.findall('-[0-9.]+/[0-9.]+',calculate)[0]
            result = re.findall('(-[0-9.]+)/([0-9.]+)',division)[0]
            result = float(result[0])/float(result[1])
            calculate = calculate.replace(division,str(result))
        else:
            division = re.findall('[0-9.]+/[0-9.]+',calculate)[0]
            result = re.findall('([0-9.]+)/([0-9.]+)',division)[0]
            result = float(result[0])/float(result[1])
            calculate = calculate.replace(division,str(result))
    while '*' in calculate:
        if re.findall('^-[0-9.]+\*[0-9.]+', calculate):
            multiplication = re.findall('-[0-9.]+\*[0-9.]+',calculate)[0]
            result = re.findall('(-[0-9.]+)\*([0-9.]+)',multiplication)[0]
            result = float(result[0])*float(result[1])
            calculate = calculate.replace(multiplication,str(result))
        else:
            multiplication = re.findall('[0-9.]+\*[0-9.]+', calculate)[0]
            result = re.findall('([0-9.]+)\*([0-9.]+)', multiplication)[0]
            result = float(result[0]) * float(result[1])
            calculate = calculate.replace(multiplication, str(result))
    return calculate

# 定义一个处理只有加减法的函数
def addition_subtraction(calculate):
    if '+-' in calculate:
        calculate = calculate.replace('+-','-')
    elif '--' in calculate:
        calculate = calculate.replace('--','+')
    list_number = []
    list_number_ = re.findall('[+-]?[0-9.]+',calculate)
    for i in list_number_:
        list_number.append(float(i))
    return sum(list_number)


# 找到最里面的括号,并传给前面的乘除法运算和加减法运算,得到最终的结果
def final(x):
    while '(' in x:
        process = re.findall('\(([^()]+)\)',x)
        for calculate in process:
            y = multiplication_division(calculate)
            y = addition_subtraction(y)
            x = x.replace('('+calculate+')',str(y))
    x = multiplication_division(x)
    return addition_subtraction(x)
print(final(x))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容