home changes contents help options

192:有理数を使う

Python 2.6 から、有理数を表現するためのモジュール fractions が標準ライブラリに追加されています。

有理数型 Fraction のインスタンスは整数を 2 つ指定して生成します。有理数型の操作は他の数値型と大差ありません。各種演算子を用いての四則演算や比較演算が可能です。

>>> from fractions import Fraction
>>> a = Fraction(1, 2) # 2 分の 1
>>> b = Fraction(1, 3) # 3 分の 1
>>> a + b # 2 分の 1 足す 3 分の 1 は?
Fraction(5, 6)
>>> a > b # 2 分の 1 のほうが大きい?
True

コンストラクタは 2 つの整数以外も受け取ります。

>>> Fraction(4) # 分母の指定を省略すると分母は 1 になる
Fraction(4, 1)
>>> Fraction() # 分子の指定も省略すると有理数 0/1 になる
Fraction(0, 1)
>>> Fraction('2/7') # 文字列から有理数に変換することもできる
Fraction(2, 7)

約分は自動で行われます。

>>> Fraction(10, 50) # インスタンス作成時に約分される
Fraction(1, 5)
>>> Fraction(1, 2) + Fraction(1, 2) # 演算結果も約分される
Fraction(1, 1)

分子や分母にアクセスするには numerator, denominator 属性を使います。

>>> a = Fraction(1, 2)
>>> a.numerator # 分子を得る
1
>>> a.denominator # 分母を得る
2

整数、浮動小数点数へ変換することが可能です。その際、誤差が発生することがあります。

>>> a = Fraction(1, 3)
>>> int(a)
0
>>> float(a)
0.33333333333333331

通常、有理数は整数の組から作りますが浮動小数点数から強制変換することもできます。

>>> Fraction.from_float(0.5) # 2 進浮動小数点数から
Fraction(1, 2)
>>> from decimal import Decimal
>>> Fraction.from_decimal(Decimal('0.5')) # 10 進浮動小数点数から
Fraction(1, 2)

from_float を使用した場合など、分子、分母が巨大な有理数ができあがることがあります。こういった値は処理に無駄に時間がかかったり、出力しても可読性に難があったりと問題があります。こうした値の近似値を得るには limit_denominator(max_denominator=1000000) メソッドが役に立ちます。このメソッドは分母を max_denominator 引数以内に抑えた、近似有理数を返します。

>>> Fraction.from_float(0.3) # 0.3 は 2 進浮動小数点数で 正確に表現できていないためこうなる
Fraction(5404319552844595, 18014398509481984)
>>> Fraction.from_float(0.3).limit_denominator() # 分母を 1000000 以内に制限する
Fraction(3, 10)

型チェックが必要な場合は fractions.Fraction と直接突き合わせてもよいですが、より抽象的である numbers.Rational とのほうがよいでしょう。

>>> import numbers
>>> isinstance(Fraction(1, 2), numbers.Rational)
True