【python基礎筆記-3】decimal模組解決浮點數計算精度問題
阿新 • • 發佈:2021-09-06
通過Decimal('123.456')物件例項化後做 + - * / 等運算子操作計算結果不會出現精度問題。
Tips:值得注意的2點是
1.Decimal接收的入參是str,所以如果原本操作的資料型別是float需要提前強轉為str。
2.decimal模組中getcontext().prec屬性可以設定小數位,但是該設定是全域性的,有可能會影響計算結果,比如a/b計算之前a和b已經被四捨五入2位小數了,再通過計算獲得的結果必然不準,所以不如必要使用該值時勁量設大點,或者不用該設定,直接把計算結果round處理。
from decimal import Decimal, getcontextfrom datetime import datetime from dateutil.relativedelta import relativedelta class RepaymentCalculator(): # 等額本金還款計劃試算 def EP_cal(self, amount, apr, installments: int, start_date=None) -> list: # getcontext().prec = 2 ,此操作有風險 per_principal = Decimal(str(amount)) / Decimal(str(installments)) mpr= Decimal(str(apr)) / Decimal(str('360')) * Decimal(str('30')) # print(float(mpr)) ,如果上面設定了prec=2此時計算出來的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): installment_interest_start_date = start_date + relativedelta(months=i) 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) # 先通過Decimal計算,再float轉換,再round取精度 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(installment_interest_start_date + relativedelta(months=1), '%Y-%m-%d') plans.append(plan_info) return plans