iT邦幫忙

1

【python內建模組- decimal】精確的浮點數運算

在python及許多程式語言中,普通的浮點數運算會產生誤差,
例如:

>>> 0.1 + 0.1 + 0.1
0.30000000000000004

decimal模組可以精準的計算小數點運算,
並且可以指定有效位數進位的方式(如: 四括五入、無條件捨去、無條件進位)

範例- 高精確度的根號運算

範例例題: zerojudge- d427: 大數根號
題意: 給定一個正整數,求平方根無條件捨去到小數點後第 50 位。

題目要求的準確度非常高,
用decimal模組則可以很方便的計算

from decimal import *

getcontext().prec = 100 #設定有效位數(注意是有效位數,而非單純指小數點後的有效位數)
getcontext().rounding = ROUND_DOWN #無條件捨去
#或寫 setcontext(Context(prec=55,rounding=ROUND_DOWN))

while True:
    try:
        line=input().strip()
        print(f"{Decimal(line).sqrt():.50f}")
    except:
        break

範例- 大數費式數列

範例例題: zerojudge- d283: 大數加法
題意: 費式數列F0=0, F1=1, F(n)=F(n-1)+F(n-2),求F(n)在n很大時候的值
限制:

  • n最大可以到二萬,由於記憶體空間有限,不能建表把數字存起來。
  • 測資最多有100筆,若每次都用遞迴關係式重新計算F(n)的話可能超時。
  • Fn其實有公式解,F(n)= sqrt_5/5 * (((1+sqrt_5)/2)**n - ((1-sqrt_5)/2)**n)(sqrt_5是根號5,**是次方),但一般可能有浮點數精確度不足的問題

要求用公式解算F(n),又要克服精確度的問題,
故此題也適合用decimal模組來解

from decimal import *
getcontext().prec = 6000

def fib(n):
    sqrt_5 = Decimal(5).sqrt()
    return sqrt_5/5 * (((1+sqrt_5)/2)**n - ((1-sqrt_5)/2)**n)

while True:
    try:
        n = int(input())
        print(f"{fib(n):.0f}")
    except:
        break

參考資料

  1. python官方文檔: decimal --- 十進制定點和浮點運算

尚未有邦友留言

立即登入留言