AI - 4.06.その他の標準ライブラリ Editorial /

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

問題

本節には練習問題はありません。

前のページ | 次のページ