【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

 

posted @ 2021-09-06 18:08  偷月  阅读(438)  评论(0编辑  收藏  举报