Python >> python チュートリアル >  >> Python

Python の Decimal 型の説明

Decimal クラスは、金融タイプの加算、減算、乗算、除算タイプの問題に最適です:

>>> (1.1+2.2-3.3)*10000000000000000000
4440.892098500626                            # relevant for government invoices...
>>> import decimal
>>> D=decimal.Decimal
>>> (D('1.1')+D('2.2')-D('3.3'))*10000000000000000000
Decimal('0.0')

Fraction モジュールは、あなたが説明した有理数の問題ドメインでうまく機能します:

>>> from fractions import Fraction
>>> f = Fraction(1) / Fraction(3)
>>> f
Fraction(1, 3)
>>> f * 3 < 1
False
>>> f * 3 == 1
True

科学研究用の純粋な多精度浮動小数点については、mpmath を検討してください。

あなたの問題が象徴的な領域にとどまることができるなら、sympy を検討してください。 1/3 の問題を処理する方法は次のとおりです。

>>> sympy.sympify('1/3')*3
1
>>> (sympy.sympify('1/3')*3) == 1
True

Sympy は、任意精度の浮動小数点に mpmath を使用し、有理数と無理数をシンボリックに処理する機能を備えています。

√2 の無理数の純粋な浮動小数点表現を考えてみましょう:

>>> math.sqrt(2)
1.4142135623730951
>>> math.sqrt(2)*math.sqrt(2)
2.0000000000000004
>>> math.sqrt(2)*math.sqrt(2)==2
False

sympy との比較:

>>> sympy.sqrt(2)
sqrt(2)                              # treated symbolically
>>> sympy.sqrt(2)*sympy.sqrt(2)==2
True

値を減らすこともできます:

>>> import sympy
>>> sympy.sqrt(8)
2*sqrt(2)                            # √8 == √(4 x 2) == 2*√2...

ただし、注意しないと、ストレート浮動小数点に似た Sympy の問題が発生する可能性があります。

>>> 1.1+2.2-3.3
4.440892098500626e-16
>>> sympy.sympify('1.1+2.2-3.3')
4.44089209850063e-16                   # :-(

これは、Decimal を使用した方が適切です:

>>> D('1.1')+D('2.2')-D('3.3')
Decimal('0.0')

または Fractions または Sympy を使用し、 1.1 などの値を保持します 比率として:

>>> sympy.sympify('11/10+22/10-33/10')==0
True
>>> Fraction('1.1')+Fraction('2.2')-Fraction('3.3')==0
True

または、sympy で Rational を使用します:

>>> frac=sympy.Rational
>>> frac('1.1')+frac('2.2')-frac('3.3')==0
True
>>> frac('1/3')*3
1

sympy liveで遊べます。


それで、私の質問は次のとおりです:無限の精度を持つ Decimal 型を持つ方法はありますか?

いいえ、無理数を格納するには無限のメモリが必要になるためです。

どこで Decimal 値が正確である必要があり、精度がアプリオリにわかっている金額などを表すのに役立ちます。

質問から、 Decimal が完全に明確ではありません float よりもユースケースに適しています .


無限の精度を持つ Decimal 型を持つ方法はありますか?

いいえ;実線上の空でない区間では、セット内のすべての数値を有限数のビットを使用して無限の精度で表現することはできません。これが Fraction の理由です 分子と分母を整数として保存するので便利です。できる 正確に表現する:

>>> Fraction("1.25")
Fraction(5, 4)