用python的正則表達式實現簡單的計算器功能


#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys
import re

def welcome_func():
	"""
	輸入判斷
	:param expression: 表達式
	:return: 返回有效表達式
	"""
	welcome_str = "超級計算器"
	print(welcome_str.center(50,'*'),'\n')  # 輸出歡迎界面
	while True:
		iput = input("請輸入你要計算的表達式[q:退出]:").strip()
		if iput == 'q':  # 退出計算
			sys.exit("bye-bye")
		elif len(iput) == 0:
			continue
		else:
			iput = re.sub('\s*', '', iput)  # 去除空格 
			return iput

def chengchu(expression):
	"""
	乘除運算
	:param expression: 表達式
	:return: 返回沒有乘除的表達式/最終計算結果
	"""
	val = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', expression)  # 匹配乘除號
	if not val:  # 乘除號不存在,返回輸入的表達式
		return expression
	data =  re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', expression).group()  # 匹配乘除號
	if len(data.split('*')) > 1:  # 當可以用乘號分割,證明有乘法運算
		part1, part2 = data.split('*')  # 以乘號作為分割符
		value = float(part1) * float(part2)  # 計算乘法
	else:
		part1, part2 = data.split('/')  # 用除號分割
		if float(part2) == 0:  # 如果分母為0,則退出計算
			sys.exit("計算過程中有被除數為0的存在,計算表達式失敗!")
		value = float(part1) / float(part2)  # 計算除法

	#print("計算:%s=%s:" % (data,value) )
	# 獲取第一個匹配到的乘除計算結果value,將value放回原表達式
	s1, s2 = re.split('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', expression, 1)  # 分割表達式
	#print("上一個表達式:",expression)
	next_expression  = "%s%s%s" % (s1, value, s2)  # 將計算結果替換會表達式
	#print("下一個表達式%s" % next_expression)
	return chengchu(next_expression)  # 遞歸表達式



def jiajian(expression):
	"""
	加減運算
	:param expression: 表達式
	:return: 返回沒有加減的表達式/最終計算結果
	"""
	expression = expression.replace('+-','-')   # 替換表達式里的所有'+-'
	expression = expression.replace('--','+')   # 替換表達式里的所有'--'
	expression = expression.replace('-+','-')   # 替換表達式里的所有'-+'
	expression = expression.replace('++','+')   # 替換表達式里的所有'++'
	#print("處理特殊加減后的表達式:",expression)
	data = re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*', expression)   # 匹配加減號
	if not data:   # 如果不存在加減號,則證明表達式已計算完成,返回最終結果
		return expression
	val = re.search('[\-]?\d+\.*\d*[\+\-]{1}\d+\.*\d*', expression).group()
	if len(val.split('+')) > 1:   # 以加號分割成功,有加法計算
		part1, part2 = val.split('+')
		value = float(part1) + float(part2)   # 計算加法
	elif val.startswith('-'):  # 如果是已'-'開頭則需要單獨計算
		part1, part2, part3  = val.split('-')
		value = -float(part2) - float(part3)  # 計算以負數開頭的減法
	else:
		part1, part2 = val.split('-')
		value = float(part1) - float(part2)  # 計算減法
	
	s1, s2 =  re.split('[\-]?\d+\.*\d*[\+\-]{1}\d+\.*\d*', expression, 1)  # 分割表達式
	#print("計算%s=%s" % (val,value))
	next_expression = "%s%s%s" % (s1, value, s2)   # 將計算后的結果替換回表達式,生成下一個表達式
	#print("下一個表達式: ",next_expression)
	return jiajian(next_expression)  # 遞歸運算表達式


def del_bracket(expression):
	"""
	小括號去除運算
	:param expression: 表達式
	:return:
	"""
	if not re.search(r'\(([^()]+)\)',expression):   # 判斷小括號,如果不存在小括號,直接調用乘除,加減計算
		ret1 = chengchu(expression)
		ret2 = jiajian(ret1)
		return ret2	  # 返回最終計算結果
	data = re.search(r'\(([^()]+)\)', expression).group()  # 如果有小括號,匹配出優先級最高的小括號
	#print("獲取表達式",data)
	data = data.strip('[\(\)]')   # 剔除小括號
	ret1 = chengchu(data)   # 計算乘除
	#print("全部乘除計算完后的表達式:",ret1)
	ret2 = jiajian(ret1)   # 計算加減
	#print("全部加減計算結果:",ret2)
	part1, replace_str, part2 = re.split(r'\(([^()]+)\)', expression, 1)  # 將小括號計算結果替換回表達式
	expression = '%s%s%s' % (part1, ret2, part2)  # 生成新的表達式
	return del_bracket(expression)  # 遞歸去小括號
	

if __name__ == "__main__":
	try:
		expression = welcome_func()   # 獲取到的表達式
	    #expression = "-1+ 3 *(-3*2-2/-2+1)/2"
	    #expression = '1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
		reslut = eval(expression)   # 用eval計算驗證
		ret = del_bracket(expression)  # 用函數計算后得出的結果
		reslut = float(reslut)
		ret = float(ret)
		if reslut == ret:   # 將兩種方式計算的結果進行比較,如果相等,則計算正確,輸出結果
			print("eval計算結果:%s" % reslut)
			print("表達式計算結果:%s" % ret)
		else:   # 兩種計算方式的結果不正確,提示異常,並返回兩種方式的計算結果
			print("計算結果異常,請重新檢查!")
			print("eval計算結果:%s" % reslut)
			print("表達式計算結果:%s" % ret)
	except(SyntaxError,ValueError,TypeError):   # 如果有不合法輸出,則拋出錯誤
		print("輸入表達式不合法,請重新檢查!")

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM