【python笔记-3】decimal模块解决浮点数计算精度问题
通过Decimal('123.456')对象实例化后做 + - * / 等运算符操作计算结果不会出现精度问题。
Tips:值得注意的2点是
1.Decimal接收的入参是str,所以如果原本操作的数据类型是float需要提前强转为str。
2.decimal模块中getcontext().prec属性可以设置小数位,但是该设置是全局的,有可能会影响计算结果,比如a/b计算之前a和b已经被四舍五入2位小数了,再通过计算获得的结果必然不准,所以不如必要使用该值时劲量设大点,或者不用该设置,直接把计算结果round处理。
class RepaymentCalculator(): # 等额本金还款计划试算 def EP_cal(self, amount, apr, installments: int, start_date=None) -> list: # getcontext().prec = 2 ,该设置会有影响mpr计算精度的风险 per_principal = Decimal(str(amount)) / Decimal(str(installments)) mpr = Decimal(str(apr)) / Decimal(str('360')) * Decimal(str('30')) # print(float(mpr)) if start_date == None: start_date = datetime.today() else: start_date = datetime.strptime(start_date, '%Y-%m-%d') plans = [] for i in range(0, installments): if i == 0: installment_interest_start_date = start_date + relativedelta(months=i) else: installment_interest_start_date = start_date + relativedelta(months=i) + relativedelta(days=1) plan_info = {} principal = Decimal(str(amount)) - Decimal(str(per_principal)) * Decimal(str(i)) interest = Decimal(str(principal)) * Decimal(str(mpr)) plan_info['principal'] = round(float(per_principal), 2) plan_info['interest'] = round(float(interest), 2) plan_info['installment'] = i + 1 plan_info['installment_interest_start_date'] = datetime.strftime(installment_interest_start_date, '%Y-%m-%d') plan_info['due_date'] = datetime.strftime(start_date + relativedelta(months=i + 1), '%Y-%m-%d') plans.append(plan_info) return plans