python 解决 eval 函数 计算 关于浮点数误差问题
项目一
首先 eval本身转化的是二进制的数据,转化过程中再转换回来肯定带有小数位,那直接使用eval对表达式进行计算,但是由于eval是将表达式中的数值使用浮点型进行计算,会由于精度的问题产生误差。
例如eval(‘8.51*13.5’)=114.88499999999999,四舍五入保留两位小数之后,结果为:114.88,会产生0.01的误差
所以为了解决这个问题, 再本项目中 我写了一个方法可以提供转化,需要提供两个参数的值,一个是提供需要计算的公式:公式不限制长度 ,第二个是需要提供一个字典。
from decimal import Decimal
def add_decimal(args):
return f"Decimal('{args}')"
def add(dict_data:dict, formula):
dic = {}
for i in dict_data.keys():
if i in formula:
y = add_decimal(str(dict_data[i]))
dic[i] = y
print(dic)
mula = []
for i in formula:
if i.strip():
mula.append(i)
print(mula)
text = ''
for i in mula:
if i in dic.keys():
i = dic[i]
text += i
else:
text += i
# print(text,"=",eval(text))
return eval(text)
if __name__ == '__main__':
formula = 'A * B + C'
dict = {'A': '8.51', 'B': '13.5', 'C':'1000'}
print(add(dict,formula)) # 运行结果 1114.885
觉得有用点赞加关注吧 写代码不容易!
项目二
写了一个关于公式断言和字符串断言的方法,返回结果是[预期结果,实际结果,True/False]
成功为True ,失败为False
import json
from decimal import Decimal
def add_decimal(args):
return f"Decimal('{args}')"
def add(dict_data:dict, formula):
dic = {}
for i in dict_data.keys():
if i in formula:
y = add_decimal(str(dict_data[i]))
dic[i] = y
mula = []
for i in formula:
if i.strip():
mula.append(i)
text = ''
for i in mula:
if i in dic.keys():
i = dic[i]
text += i
else:
text += i
return eval(text)
def str_split(formula:str,expect:str):
formula = formula.split(',')
expect = expect.split(',')
return formula,expect
def compare_fixvalue(dic:dict, expect:str):
""" 字符串断言
dic = {'E': 'lll', 'SDSD abc': 'ABC', 'F': 'ooo', "Venue": "HV", "Total": "1,000.00", "ACP8": "","AA":"1"}
expect = '{"Venue":"HV","Total":"1,000.00","ACP8":"","AA":"2"}'
status = compare_fixvalue(dic, expect)
预期结果,实际结果 返回值
[['HV', 'HV', True], ['1,000.00', '1,000.00', True], ['', '', True], ['2', '1', False]]
"""
status_list = []
dict_expect = json.loads(expect)
for i in dict_expect.keys():
if dict_expect[i] in dic.values():
if dict_expect[i] in dic[i]:
result_list = [dict_expect[i], dic[i], True]
status_list.append(result_list)
# print(f'预期结果 value:{dict_expect[i]}, 实际结果 value:{dic[i]}, True')
else:
result_list = [dict_expect[i], dic[i], False]
status_list.append(result_list)
# print(f'预期结果 value:{dict_expect[i]}, 实际结果 value:{dic[i]}, False')
else:
if i not in dic.keys():
result_list = [i, 'None key', False]
status_list.append(result_list)
# print(f'预期结果 key:{i}, 实际结果找不到对应 key, False')
else:
result_list = [dict_expect[i], dic[i], False]
status_list.append(result_list)
# print(f'预期结果 value:{dict_expect[i]}, 实际结果 value:{dic[i]}, False')
return status_list
def spare_compare_fixvalue(dic:dict, formula:str, expect:str):
""" 备用 字符串断言
dic = {'E':'lll','SDSD abc':'ABC','F':'ooo'}
formula = 'E,SDSD abc,F'
expect = 'lll,ABC,oo'
status = spare_compare_fixvalue(dic, formula, expect)
print(status)
比较值相等 返回 True 否则 False
"""
status_list = []
formula, expect = str_split(formula,expect)
if len(formula) != len(expect):
raise Exception("预期结果与实际结果条数不一致")
else:
for i in range(len(formula)):
status = analyze_fixvalue(dic,formula[i],expect[i])
status_list.append(status)
status_value = [str(j) for j in status_list]
# status_value = "" + join(status_value)
return status_value
def analyze_fixvalue(dic:dict, formula, expect):
""" dic :字典数据 ,formula :实际结果str ,expect:预期结果str"""
formula, expect = formula.strip(), expect.strip()
if str(formula).isalpha() is True or formula.isspace() is False:
formula = dic[formula] # print('实际结果',formula) # print('预期结果',expect)
try:
if formula == expect:
print(f'expect: {expect}, actual: {formula}, return:',True)
return True
else:
print(f'expect: {expect} != actual: {formula} return:',False)
return False
except Exception as e:
print(f'raise Exception 异常 --> {e}')
return False
else:
raise Exception("预期结果不仅仅包含字母或字符串带中间空格,请调用 compare_fumula 方法")
def compare_fumula(dic:dict, formula:str, expect:str):
""" 公式断言
dic = {'A': '2', 'B': '3', 'C': '5', 'D': '5'}
# 公式断言
# formula = 'A + B, B + C,B + C'
# expect = 'A + B, B + C,B + C'
## status = compare_fumula(dic, formula,'5.4') # 输入实际值
# status = compare_fumula(dic, formula, expect) # 输入字典 value
预期结果,实际结果 返回值
[['A + B', 'A + B', True], [' B + C', ' B + C', True], ['B + C', 'B + C', True]]
"""
status_list = []
formula, expect = str_split(formula,expect)
if len(formula) != len(expect):
raise Exception("预期结果与实际结果条数不一致")
else:
for i in range(len(formula)):
status = analyze_formula(dic,formula[i],expect[i])
value = [expect[i],formula[i],status]
status_list.append(value)
return status_list
def analyze_formula(dic:dict, formula, expect, deviation=0.0):
""" dic :PDF字典数据 ,formula :计算公式 ,expect:预期结果 ,deviation 可控制范围 """
formula, expect = formula.strip(), expect.strip()
expect_value = None
if expect in '+' or '-' or '*' or '/':
expect_value = add(dic, str(expect))
# print("预期结果 :",expect_value)
else:
expect = dic[expect] if str(expect).isalpha() is True else expect
expect = eval(expect)
expect = expect_value if expect_value is not None else expect
actual = add(dic, formula)
# print("实际结果 :",actual)
try:
assert float(deviation) == abs(actual - expect)
# print(f'expect:{expect}, actual:{actual}, Controllable range:{deviation}')
return True
except AssertionError as error:
# print(f'raise AssertionError 异常 --> expect:{expect},actual:{actual} ', error.__str__())
return False
if __name__ == '__main__':
# 公式断言
dic = {'A': '1232.012', 'B': '1252.018', 'C': '5', 'D': '5'}
formula = 'B * A, D + B, B + C' # 计算公式
expect = 'A * B, D + B, A + B' # 预期结果:写入公式、数字、都可,与计算公式个数对应
status = compare_fumula(dic, formula, expect) # 输入字典 value
print(status)
# [['A * B', 'B * A', True], [' D + B', ' D + B', True], [' A + B', ' B + C', False]]
# 字符串断言
dic = {'E': 'lll', 'SDSD abc': 'ABC', 'F': 'ooo', "Venue": "HV", "Total": "1,000.00", "ACP8": "","AA":"1","RACE1_WIN_POOL STATUS":"DEFINED","RACE15_WIN_POOL STATUS":"DEFINED"}
expect = '{"RACE1_WIN_POOL STATUS": "DEFINED", "RACE15_WIN_POOL STATUS": "D/EFINEDZ"}'
status = compare_fixvalue(dic, expect)
print(status) # [['DEFINED', 'DEFINED', True], ['D/EFINEDZ', 'DEFINED', False]]