文章目录
需求问题
在实际使用过程中,我们会遇到很多需要计算的地方,一般情况下我们使用系统的计算方法就实现:
a = -2.3+((1.0-1.0)/(89.0-1.0)*0.4+0.6)*-5
print(a)
输出:-5.3
或者使用eval方法:
a = "-2.3+((1.0-1.0)/(89.0-1.0)*0.4+0.6)*-5"
print(eval(a))
输出:-5.3
上述两种方法都可以算出公式的结果。但是存在一定的限制。例如,如果给出的算式中存在除数为0的情况呢?那上面两种办法就行不通了。
例: (2.0-1.0)/(89.0-89.0)*0.4+0.6
,像这样的式子,计算的时候89.0-89.0结果为0,然而这个0又放在了除数的位置,所以就会发生错误。然我们的本身用意是式子中的除数为0的部分为计算结果指定为0,即式子中(2.0-1.0)/(89.0-89.0)
该部分结果指定为0,后续的正常计算,那该式子的计算结果最终就等于0.6了。
要想要达到我们这样的目的,那上述的方法就行不通,于是我们就需要自己来实现四则运算。
解决方案
例:-2.3+((1.0-1.0)/(89.0-1.0)*0.4+0.6)*-5
,因为我们的需求是式子中可能包含小数,或者负数,在我们人工计算的时候,我们会区分开哪个是整数,哪个是小数,哪个是负数,这样我们才能进行计算;所以我们在用程序计算这个式子的时候,我们也得需要区分开哪个是整数,哪个是小数,哪个是负数,即我们需要将式子转化为:
['-2.3', '+', '(', '(', '1.0', '-', '1.0', ')', '/', '(', '89.0', '-', '1.0', ')', '*', '0.4', '+', '0.6', ')', '*', '-5']
如果按照字符切分的话,那就会将上面的式子切成单个字符,如-2.3
被切割成['-', '2', '.', '3']
,这样肯定是不对的,切割成这样我们就无法计算了。
所以我们就先要对式子进行切分,切成我们用来计算的列表,就如同这样的式子:
['-2.3', '+', '(', '(', '1.0', '-', '1.0', ')', '/', '(', '89.0', '-', '1.0', ')', '*', '0.4', '+', '0.6', ')', '*', '-5']
然后我们才能进行后续的操作。
第一步:对算式进行切割,得到可以进行计算的列表;
第二步:将公式转化为后缀表达式(用栈实现);
第三步:从左到右依次访问后缀表达式,计算公式结果。
实现步骤
1、 对算式进行切割,得到可以进行计算的列表
def formula_charnge_to_list(formula):
"""
:param formula: 需要计算的公式,为全是值的公式,eg: ((1.0-1.0)/(89.0-1.0)*0.4+0.6)*5
:return: 用于入栈计算的公式列表,负数或者小数被当做一个元素, eg:['(', '(', '1.0', '-', '1.0', ')', '/', '(', '89.0', '-', '1.0', ')', '*', '0.4', '+', '0.6', ')', '*', '5']
"""
a_list1 = list(formula.replace(" ", "")) # 格式化公式,防止公式中的空格影响后续操作
a_list2 = [] # 存储最终公式列表
temp_str = ""
for i in range(len(a_list1)):
if a_list1[i] in "+*/()":
if temp_str != "":
a_list2.append(temp_str)
temp_str = ""
a_list2.append(a_list1[i])
elif a_list1[i].isalnum() or a_list1[i] == ".":
temp_str += a_list1[i]
else:
if i == 0:
temp_str += a_list1[i]
else:
if a_list1[i-1].isalnum() and a_list1[i+1].isalnum(): # 3 - 3
if temp_str != "":
a_list2.append(temp_str)
temp_str = ""
a_list2.append(a_list1[i])
elif a_list1[i-