/
Time Limit: 0 msec / Memory Limit: 0 KiB
キーポイント
fractionモジュールにより有理数型の変数を扱うことができるdecimalモジュールによりDecimal型の変数を扱うことができる
fractions
fractions モジュールが提供する Fraction クラスにより有理数型を扱うことができます。
from fractions import Fraction x = Fraction(1, 2) # 1/2 を表す y = Fraction(1, 3) # 1/3 を表す z = x + y print(z) # 5/6 print(z.numerator, z.denominator) # 5 6 print(x * 4) # 2 print(x / y) # 3/2
Fraction の計算は遅いため、使う必要があるケースを見極める必要があります。
from fractions import Fraction
def f(x):
s = 0
for i in range(10**7):
s += x
f(0.5) # 5.9 ms (AtCoderのコードテストで Python (PyPy 3.11-v7.3.20) を選択し実行した場合, 以下同様)
f(0.286) # 5.4 ms
f(Fraction(1, 2)) # 483 ms
f(Fraction(3, 7)) # 951 ms
f(Fraction(123, 457)) # 1508 ms
decimal
コンピュータの内部では値を 2 進法に変換して保持しています。そのため、2 進法で有限桁で正確に表すことができない小数を含む演算を行うと誤差が発生することがあります。
print(0.1 + 0.2 == 0.3) # False !!!
もし扱う数が 10 進法では有限桁であることが最初から分かっている場合、decimal モジュールが提供する Decimal クラスにより値を扱うことができます。
from decimal import Decimal
a = Decimal("0.1")
b = Decimal("0.2")
c = Decimal("0.3")
print(a + b) # 0.3
print(a + b == c) # True
0.1 など、最初からわかっている値を Decimal 型に変換する際は Decimal(0.1) ではなく Decimal("0.1") と記述する必要があります。 0.1 は 2 進法では有限桁で正確に表すことができないため書いた瞬間から誤差を持ち、誤差を持つ値が Decimal 型に変換されるためです。同様に、float 型で計算したあとの値を Decimal 型に変換しても、それが正確とは限りません。
a = Decimal("0.1")
print(a) # 0.1
x = Decimal(0.1)
print(x) # 0.1000000000000000055511151231257827021181583404541015625
b = 3 / 10
y = Decimal(b)
print(y) # 0.299999999999999988897769753748434595763683319091796875
Decimal 型も float 型と同様、10進法で有限桁で正確に表すことができない小数を含む演算を行うと誤差が発生することがあります。
from decimal import Decimal a = Decimal(1) b = Decimal(3) print(a / b * b) # 0.9999999999999999999999999999 print(a / b * b == a) # False
Decimal 型に対する演算は非常に遅いため、使う必要があるケースを見極める必要があります。
from decimal import Decimal
def f(x):
s = 0
for i in range(10**6):
s+=x
f(0.5) # 1.1 ms (AtCoderのコードテストで Python (PyPy 3.11-v7.3.20) を選択し実行した場合, 以下同様)
f(0.286) # 0.6 ms
f(Decimal(0.5)) # 63 ms
f(Decimal(0.286)) # 1934 ms
f(Decimal(0.123456789)) # 1886 ms
問題
本節には練習問題はありません。