10進数— 10進数の固定小数点および浮動小数点演算—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.8/library/decimal
移動先:案内検索

10進数 —10進数の固定小数点および浮動小数点演算

ソースコード: :source: `Lib / decimal.py`



decimal モジュールは、正しく丸められた10進浮動小数点演算の高速化をサポートします。 float データ型に比べていくつかの利点があります。

  • Decimalは、「人々を念頭に置いて設計された浮動小数点モデルに基づいており、必然的に最も重要なガイド原則があります。コンピューターは、人々が学校で学ぶ算術と同じように機能する算術を提供する必要があります。」 –10進算術仕様からの抜粋。

  • 10進数は正確に表すことができます。 対照的に、1.12.2のような数値は、2進浮動小数点で正確に表現されていません。 エンドユーザーは通常、バイナリ浮動小数点の場合のように1.1 + 2.23.3000000000000003として表示されることを期待しません。

  • 正確さは算術に引き継がれます。 10進浮動小数点では、0.1 + 0.1 + 0.1 - 0.3は正確にゼロに等しくなります。 バイナリ浮動小数点では、結果は5.5511151231257827e-017です。 ゼロに近い間、違いは信頼できる同等性テストを妨げ、違いは蓄積する可能性があります。 このため、厳密な等式不変量を持つ会計アプリケーションでは、10進数が推奨されます。

  • 小数モジュールには、1.30 + 1.202.50になるように、重要な場所の概念が組み込まれています。 末尾のゼロは、重要性を示すために保持されます。 これは、金銭的アプリケーションの通常のプレゼンテーションです。 掛け算の場合、「教科書」アプローチでは、被乗数のすべての数値を使用します。 たとえば、1.3 * 1.21.56を提供し、1.30 * 1.201.5600を提供します。

  • ハードウェアベースのバイナリ浮動小数点とは異なり、decimalモジュールにはユーザーが変更可能な精度(デフォルトは28桁)があり、特定の問題に必要なだけ大きくすることができます。

    >>> from decimal import *
    >>> getcontext().prec = 6
    >>> Decimal(1) / Decimal(7)
    Decimal('0.142857')
    >>> getcontext().prec = 28
    >>> Decimal(1) / Decimal(7)
    Decimal('0.1428571428571428571428571429')
  • 2進浮動小数点と10進浮動小数点の両方が、公開されている標準の観点から実装されています。 組み込みのfloat型はその機能の適度な部分のみを公開しますが、decimalモジュールは標準の必要なすべての部分を公開します。 必要に応じて、プログラマーは丸めと信号処理を完全に制御できます。 これには、例外を使用して不正確な操作をブロックすることにより、正確な算術演算を強制するオプションが含まれます。

  • 10進モジュールは、「正確な丸められていない10進演算(固定小数点演算と呼ばれることもあります)と丸められた浮動小数点演算の両方を害することなく」サポートするように設計されています。 –10進算術仕様からの抜粋。

モジュールの設計は、10進数、算術演算のコンテキスト、および信号の3つの概念を中心にしています。

10進数は不変です。 符号、係数の数字、および指数があります。 有意性を維持するために、係数の数字は後続のゼロを切り捨てません。 小数には、Infinity-InfinityNaNなどの特別な値も含まれます。 この規格では、-0+0も区別されています。

算術演算のコンテキストは、精度、丸め規則、指数の制限、操作の結果を示すフラグ、および信号を例外として処理するかどうかを決定するトラップイネーブラーを指定する環境です。 丸めオプションには、 ROUND_CEILINGROUND_DOWNROUND_FLOORROUND_HALF_DOWNROUND_HALF_EVEN 、 RO_ 、 ROUND_UP 、および ROUND_05UP

信号は、計算の過程で発生する例外的な条件のグループです。 アプリケーションのニーズに応じて、シグナルは無視されるか、情報提供と見なされるか、例外として扱われる場合があります。 10進モジュールの信号は、 ClampedInvalidOperationDivisionByZeroInexactRoundedです。 ]異常オーバーフローアンダーフローおよびフロート操作

各信号には、フラグとトラップイネーブラーがあります。 信号が検出されると、そのフラグが1に設定され、トラップイネーブラーが1に設定されると、例外が発生します。 フラグはスティッキーであるため、ユーザーは計算を監視する前にフラグをリセットする必要があります。

も参照してください


クイックスタートチュートリアル

小数の使用の通常の開始は、モジュールをインポートし、 getcontext()で現在のコンテキストを表示し、必要に応じて、精度、丸め、または有効なトラップに新しい値を設定することです。

>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero,
        InvalidOperation])

>>> getcontext().prec = 7       # Set a new precision

10進数のインスタンスは、整数、文字列、浮動小数点数、またはタプルから構成できます。 整数または浮動小数点数からの構築は、その整数または浮動小数点数の値の正確な変換を実行します。 10進数には、「数値ではない」を表すNaN、正と負のInfinity-0などの特別な値が含まれます。

>>> getcontext().prec = 28
>>> Decimal(10)
Decimal('10')
>>> Decimal('3.14')
Decimal('3.14')
>>> Decimal(3.14)
Decimal('3.140000000000000124344978758017532527446746826171875')
>>> Decimal((0, (3, 1, 4), -2))
Decimal('3.14')
>>> Decimal(str(2.0 ** 0.5))
Decimal('1.4142135623730951')
>>> Decimal(2) ** Decimal('0.5')
Decimal('1.414213562373095048801688724')
>>> Decimal('NaN')
Decimal('NaN')
>>> Decimal('-Infinity')
Decimal('-Infinity')

FloatOperation シグナルがトラップされた場合、コンストラクターまたは順序比較で小数と浮動小数点が誤って混在すると、例外が発生します。

>>> c = getcontext()
>>> c.traps[FloatOperation] = True
>>> Decimal(3.14)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Decimal('3.5') < 3.7
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Decimal('3.5') == 3.5
True

バージョン3.3の新機能。


新しい10進数の重要性は、入力された桁数によってのみ決定されます。 コンテキストの精度と丸めは、算術演算中にのみ機能します。

>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')

Cバージョンの内部制限を超えた場合、小数を作成すると InvalidOperation が発生します。

>>> Decimal("1e9999999999999999999")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

バージョン3.3で変更されました。


10進数は、Pythonの他の多くの部分とうまく相互作用します。 これは、小さな10進浮動小数点浮動小数点サーカスです。

>>> data = list(map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()))
>>> max(data)
Decimal('9.25')
>>> min(data)
Decimal('0.03')
>>> sorted(data)
[Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),
 Decimal('2.35'), Decimal('3.45'), Decimal('9.25')]
>>> sum(data)
Decimal('19.29')
>>> a,b,c = data[:3]
>>> str(a)
'1.34'
>>> float(a)
1.34
>>> round(a, 1)
Decimal('1.3')
>>> int(a)
1
>>> a * 5
Decimal('6.70')
>>> a * b
Decimal('2.5058')
>>> c % a
Decimal('0.77')

また、いくつかの数学関数もDecimalで使用できます。

>>> getcontext().prec = 28
>>> Decimal(2).sqrt()
Decimal('1.414213562373095048801688724')
>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal('10').ln()
Decimal('2.302585092994045684017991455')
>>> Decimal('10').log10()
Decimal('1')

quantize()メソッドは、数値を固定指数に丸めます。 この方法は、結果を固定数の場所に丸めることが多い金銭的アプリケーションに役立ちます。

>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')

上に示したように、 getcontext()関数は現在のコンテキストにアクセスし、設定を変更できるようにします。 このアプローチは、ほとんどのアプリケーションのニーズを満たします。

より高度な作業では、Context()コンストラクターを使用して代替コンテキストを作成すると便利な場合があります。 代替をアクティブにするには、 setcontext()関数を使用します。

標準に従って、 10進数モジュールは、すぐに使用できる2つの標準コンテキスト BasicContextExtendedContext を提供します。 前者は、トラップの多くが有効になっているため、デバッグに特に役立ちます。

>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
>>> setcontext(myothercontext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857142857142857142857142857')

>>> ExtendedContext
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        capitals=1, clamp=0, flags=[], traps=[])
>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857143')
>>> Decimal(42) / Decimal(0)
Decimal('Infinity')

>>> setcontext(BasicContext)
>>> Decimal(42) / Decimal(0)
Traceback (most recent call last):
  File "<pyshell#143>", line 1, in -toplevel-
    Decimal(42) / Decimal(0)
DivisionByZero: x / 0

コンテキストには、計算中に発生した例外的な状態を監視するための信号フラグもあります。 フラグは明示的にクリアされるまで設定されたままなので、clear_flags()メソッドを使用して、監視対象の計算の各セットの前にフラグをクリアすることをお勧めします。

>>> setcontext(ExtendedContext)
>>> getcontext().clear_flags()
>>> Decimal(355) / Decimal(113)
Decimal('3.14159292')
>>> getcontext()
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[])

flags エントリは、Piの有理近似が丸められ(コンテキスト精度を超える桁が破棄された)、結果が不正確であることを示しています(破棄された桁の一部がゼロ以外でした) 。

個々のトラップは、コンテキストのtrapsフィールドの辞書を使用して設定されます。

>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(0)
Decimal('Infinity')
>>> getcontext().traps[DivisionByZero] = 1
>>> Decimal(1) / Decimal(0)
Traceback (most recent call last):
  File "<pyshell#112>", line 1, in -toplevel-
    Decimal(1) / Decimal(0)
DivisionByZero: x / 0

ほとんどのプログラムは、プログラムの開始時に、現在のコンテキストを1回だけ調整します。 また、多くのアプリケーションでは、データはループ内で1回キャストするだけで Decimal に変換されます。 コンテキストセットと小数が作成されると、プログラムの大部分は他のPython数値型と同じようにデータを操作します。


10進オブジェクト

class decimal.Decimal(value='0', context=None)

value に基づいて新しい Decimal オブジェクトを作成します。

value は、整数、文字列、タプル、 float 、または別の Decimal オブジェクトにすることができます。 value が指定されていない場合、Decimal('0')を返します。 value が文字列の場合、先頭と末尾の空白文字、および全体の下線が削除された後、10進数の数値文字列構文に準拠する必要があります。

sign           ::=  '+' | '-'
digit          ::=  '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
indicator      ::=  'e' | 'E'
digits         ::=  digit [digit]...
decimal-part   ::=  digits '.' [digits] | ['.'] digits
exponent-part  ::=  indicator [sign] digits
infinity       ::=  'Infinity' | 'Inf'
nan            ::=  'NaN' [digits] | 'sNaN' [digits]
numeric-value  ::=  decimal-part [exponent-part] | infinity
numeric-string ::=  [sign] numeric-value | [sign] nan

digitが上に表示されている場合は、他のUnicode10進数も使用できます。 これらには、他のさまざまなアルファベットの10進数(たとえば、アラビア数字とデーバナーガリー数字)と、全幅の数字'\uff10'から'\uff19'が含まれます。

valuetuple の場合、符号(0は正、1は負)、の3つのコンポーネントが必要です。数字のタプル、および整数の指数。 たとえば、Decimal((0, (1, 4, 1, 4), -3))Decimal('1.414')を返します。

valuefloat の場合、2進浮動小数点値はロスレスで正確な10進数に変換されます。 この変換には、53桁以上の精度が必要になることがよくあります。 たとえば、Decimal(float('1.1'))Decimal('1.100000000000000088817841970012523233890533447265625')に変換されます。

context の精度は、格納される桁数には影響しません。 これは、の桁数によってのみ決定されます。 たとえば、Decimal('3.00000')は、コンテキストの精度が3つしかない場合でも、5つのゼロすべてを記録します。

context 引数の目的は、 value が不正な形式の文字列である場合の対処方法を決定することです。 コンテキストが InvalidOperation をトラップすると、例外が発生します。 それ以外の場合、コンストラクターは値がNaNの新しいDecimalを返します。

構築されると、 Decimal オブジェクトは不変になります。

バージョン3.2で変更:コンストラクターへの引数が float インスタンスとして許可されるようになりました。

バージョン3.3で変更: FloatOperation トラップが設定されている場合、 float 引数は例外を発生させます。 デフォルトでは、トラップはオフになっています。

バージョン3.6で変更:コード内の整数リテラルおよび浮動小数点リテラルと同様に、グループ化にアンダースコアを使用できます。

10進浮動小数点オブジェクトは、 floatint などの他の組み込み数値型と多くのプロパティを共有します。 通常の数学演算と特別な方法のすべてが適用されます。 同様に、10進オブジェクトは、コピー、ピクルス化、印刷、辞書キーとしての使用、セット要素としての使用、比較、並べ替え、および別の型( floatint など)への強制変換が可能です)。 。

Decimalオブジェクトの算術演算と、整数および浮動小数点数の算術演算には、いくつかの小さな違いがあります。 剰余演算子%が10進オブジェクトに適用される場合、結果の符号は除数の符号ではなく、被除数の符号になります。

>>> (-7) % 4
1
>>> Decimal(-7) % Decimal(4)
Decimal('-3')

整数除算演算子//も同様に動作し、通常のID x == (x // y) * y + x % yを維持するために、フロアではなく真の商の整数部分(ゼロに向かって切り捨て)を返します。

>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')

%および//演算子は、仕様に記載されているように、remainderおよびdivide-integer操作を(それぞれ)実装します。

10進オブジェクトは、通常、算術演算でfloatまたは fractions.Fraction のインスタンスと組み合わせることはできません。たとえば、 Decimalfloat に追加しようとすると TypeError を発生させます。 ただし、Pythonの比較演算子を使用して、 Decimal インスタンスxを別の数値yと比較することは可能です。 これにより、異なるタイプの数の間で等価比較を行うときに混乱する結果を回避できます。

バージョン3.2で変更: Decimal インスタンスと他の数値型との間の混合型の比較が完全にサポートされるようになりました。

標準の数値プロパティに加えて、10進浮動小数点オブジェクトにはいくつかの特殊なメソッドもあります。

adjusted()

係数の右端の桁をシフトアウトした後、先頭の桁のみが残るまで調整された指数を返します。Decimal('321e+5').adjusted()は7を返します。 小数点に対する最上位桁の位置を決定するために使用されます。

as_integer_ratio()

指定された Decimal インスタンスを分数として、最低条件で正の分母で表す整数のペア(n, d)を返します。

>>> Decimal('-3.14').as_integer_ratio()
(-157, 50)

変換は正確です。 無限大ではOverflowErrorを、NaNではValueErrorを発生させます。

バージョン3.6の新機能。

as_tuple()

番号の名前付きタプル表現を返します:DecimalTuple(sign, digits, exponent)

canonical()

引数の正規エンコーディングを返します。 現在、 Decimal インスタンスのエンコーディングは常に正規であるため、この操作は引数を変更せずに返します。

compare(other, context=None)

2つのDecimalインスタンスの値を比較します。 compare()はDecimalインスタンスを返し、いずれかのオペランドがNaNの場合、結果はNaNになります。

a or b is a NaN  ==> Decimal('NaN')
a < b            ==> Decimal('-1')
a == b           ==> Decimal('0')
a > b            ==> Decimal('1')
compare_signal(other, context=None)

この操作は、すべてのNaNが信号を送ることを除いて、 compare()メソッドと同じです。 つまり、どちらのオペランドもシグナリングNaNでない場合、クワイエットNaNオペランドは、シグナリングNaNであるかのように扱われます。

compare_total(other, context=None)

数値ではなく抽象表現を使用して、2つのオペランドを比較します。 compare()メソッドに似ていますが、結果は Decimal インスタンスの全順序付けになります。 数値は同じで表現が異なる2つの Decimal インスタンスは、次の順序で等しくありません。

>>> Decimal('12.0').compare_total(Decimal('12'))
Decimal('-1')

静かで信号を送るNaNも注文全体に含まれます。 この関数の結果は、両方のオペランドが同じ表現の場合はDecimal('0')、最初のオペランドが2番目のオペランドよりも全順序で低い場合はDecimal('-1')、最初のオペランドの場合はDecimal('1')です。オペランドは、2番目のオペランドよりも全順序で上位にあります。 全注文の詳細については、仕様を参照してください。

この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めも実行されません。 例外として、第2オペランドを正確に変換できない場合、CバージョンはInvalidOperationを発生させる可能性があります。

compare_total_mag(other, context=None)

compare_total()のように値ではなく抽象表現を使用して、2つのオペランドを比較しますが、各オペランドの符号は無視します。 x.compare_total_mag(y)x.copy_abs().compare_total(y.copy_abs())と同等です。

この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めも実行されません。 例外として、第2オペランドを正確に変換できない場合、CバージョンはInvalidOperationを発生させる可能性があります。

conjugate()

自己を返すだけです。このメソッドは、10進仕様に準拠するためだけのものです。

copy_abs()

引数の絶対値を返します。 この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めは実行されません。

copy_negate()

引数の否定を返します。 この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めは実行されません。

copy_sign(other, context=None)

符号が第2オペランドの符号と同じになるように設定された第1オペランドのコピーを返します。 例えば:

>>> Decimal('2.3').copy_sign(Decimal('-1.5'))
Decimal('-2.3')

この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めも実行されません。 例外として、第2オペランドを正確に変換できない場合、CバージョンはInvalidOperationを発生させる可能性があります。

exp(context=None)

指定された数の(自然な)指数関数e**xの値を返します。 結果は、 ROUND_HALF_EVEN 丸めモードを使用して正しく丸められます。

>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal(321).exp()
Decimal('2.561702493119680037517373933E+139')
from_float(f)

浮動小数点数を正確に10進数に変換するClassmethod。

注 Decimal.from_float(0.1)は、 Decimal( '0.1')と同じではありません。 0.1はバイナリ浮動小数点で正確に表現できないため、値は 0x1.999999999999ap-4 である最も近い表現可能な値として格納されます。 10進数での同等の値は 0.1000000000000000055511151231257827021181583404541015625 です。

ノート

Python 3.2以降では、 Decimal インスタンスを float から直接構築することもできます。

>>> Decimal.from_float(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> Decimal.from_float(float('nan'))
Decimal('NaN')
>>> Decimal.from_float(float('inf'))
Decimal('Infinity')
>>> Decimal.from_float(float('-inf'))
Decimal('-Infinity')

バージョン3.1の新機能。

fma(other, third, context=None)

融合乗算-加算。 中間製品self * otherを丸めずに、self * other + thirdを返します。

>>> Decimal(2).fma(3, 5)
Decimal('11')
is_canonical()

引数が正規の場合は True を返し、それ以外の場合は False を返します。 現在、 Decimal インスタンスは常に正規であるため、この操作は常に True を返します。

is_finite()

引数が有限数の場合は True を返し、引数が無限大またはNaNの場合は False を返します。

is_infinite()

引数が正または負の無限大の場合は True を返し、それ以外の場合は False を返します。

is_nan()

引数が(静かなまたはシグナリングの)NaNの場合は True を返し、それ以外の場合は False を返します。

is_normal(context=None)

引数が通常の有限数の場合、 True を返します。 引数がゼロ、非正規、無限、またはNaNの場合は、 False を返します。

is_qnan()

引数がクワイエットNaNの場合は True を返し、それ以外の場合は False を返します。

is_signed()

引数に負の符号がある場合は True を返し、それ以外の場合は False を返します。 ゼロとNaNは両方とも符号を付けることができることに注意してください。

is_snan()

引数がシグナリングNaNの場合は True を返し、それ以外の場合は False を返します。

is_subnormal(context=None)

引数が正常でない場合は True を返し、それ以外の場合は False を返します。

is_zero()

引数が(正または負の)ゼロの場合は True を返し、それ以外の場合は False を返します。

ln(context=None)

オペランドの自然な(基数e)対数を返します。 結果は、 ROUND_HALF_EVEN 丸めモードを使用して正しく丸められます。

log10(context=None)

オペランドの基数10の対数を返します。 結果は、 ROUND_HALF_EVEN 丸めモードを使用して正しく丸められます。

logb(context=None)

ゼロ以外の数値の場合、そのオペランドの調整済み指数を Decimal インスタンスとして返します。 オペランドがゼロの場合、Decimal('-Infinity')が返され、 DivisionByZero フラグが立てられます。 オペランドが無限大の場合、Decimal('Infinity')が返されます。

logical_and(other, context=None)

logical_and()は、2つの論理オペランドを使用する論理演算です(論理オペランドを参照)。 結果は、2つのオペランドの桁単位のandです。

logical_invert(context=None)

logical_invert()は論理演算です。 その結果、オペランドが桁単位で反転します。

logical_or(other, context=None)

logical_or()は、2つの論理オペランドを使用する論理演算です(論理オペランドを参照)。 結果は、2つのオペランドの桁単位のorです。

logical_xor(other, context=None)

logical_xor()は、2つの論理オペランドを使用する論理演算です(論理オペランドを参照)。 結果は、2桁の排他的論理和または2つのオペランドの排他的論理和です。

max(other, context=None)

max(self, other)と同様ですが、戻る前にコンテキスト丸めルールが適用され、NaN値が通知されるか無視されます(コンテキストと、通知するか静かにするかによって異なります)。

max_mag(other, context=None)

max()メソッドに似ていますが、比較はオペランドの絶対値を使用して行われます。

min(other, context=None)

min(self, other)と同様ですが、戻る前にコンテキスト丸めルールが適用され、NaN値が通知されるか無視されます(コンテキストと、通知するか静かにするかによって異なります)。

min_mag(other, context=None)

min()メソッドに似ていますが、比較はオペランドの絶対値を使用して行われます。

next_minus(context=None)

指定されたオペランドよりも小さい、指定されたコンテキスト(またはコンテキストが指定されていない場合は現在のスレッドのコンテキスト)で表現可能な最大数を返します。

next_plus(context=None)

指定されたオペランドよりも大きい、指定されたコンテキスト(またはコンテキストが指定されていない場合は現在のスレッドのコンテキスト)で表現可能な最小数を返します。

next_toward(other, context=None)

2つのオペランドが等しくない場合は、2番目のオペランドの方向で最初のオペランドに最も近い数値を返します。 両方のオペランドが数値的に等しい場合は、符号が2番目のオペランドの符号と同じになるように設定された最初のオペランドのコピーを返します。

normalize(context=None)

右端の後続ゼロを取り除き、Decimal('0')に等しい結果をDecimal('0e0')に変換して、数値を正規化します。 同値類の属性の正規値を生成するために使用されます。 たとえば、Decimal('32.100')Decimal('0.321000e+2')はどちらも、同等の値Decimal('32.1')に正規化されます。

number_class(context=None)

オペランドのクラスを説明する文字列を返します。 戻り値は、次の10個の文字列のいずれかです。

  • "-Infinity"は、オペランドが負の無限大であることを示します。

  • "-Normal"は、オペランドが負の正規数であることを示します。

  • "-Subnormal"は、オペランドが負で非正規であることを示します。

  • "-Zero"は、オペランドが負のゼロであることを示します。

  • "+Zero"は、オペランドが正のゼロであることを示します。

  • "+Subnormal"は、オペランドが正で非正規であることを示します。

  • "+Normal"は、オペランドが正の正規数であることを示します。

  • "+Infinity"は、オペランドが正の無限大であることを示します。

  • "NaN"は、オペランドがクワイエットNaN(数値ではない)であることを示します。

  • "sNaN"は、オペランドがシグナリングNaNであることを示します。

quantize(exp, rounding=None, context=None)

四捨五入して第2オペランドの指数をとった後、第1オペランドに等しい値を返します。

>>> Decimal('1.41421356').quantize(Decimal('1.000'))
Decimal('1.414')

他の操作とは異なり、量子化操作後の係数の長さが精度よりも大きい場合は、 InvalidOperation が通知されます。 これにより、エラー条件がない限り、量子化された指数が常に右側のオペランドの指数と等しくなることが保証されます。

また、他の操作とは異なり、結果が異常で不正確であっても、量子化はアンダーフローを通知しません。

2番目のオペランドの指数が最初のオペランドの指数よりも大きい場合は、丸めが必要になる場合があります。 この場合、丸めモードは、指定されている場合はrounding引数によって決定され、指定されていない場合は指定されたcontext引数によって決定されます。 どちらの引数も指定されていない場合、現在のスレッドのコンテキストの丸めモードが使用されます。

結果の指数がEmaxより大きいか、Etinyより小さい場合は常に、エラーが返されます。

radix()

Decimal(10)を返します。これは、 Decimal クラスがすべての算術演算を行う基数(基数)です。 仕様との互換性のために含まれています。

remainder_near(other, context=None)

selfother で割った余りを返します。 これは、self % otherとは異なり、剰余の符号はその絶対値を最小化するように選択されます。 より正確には、戻り値はself - n * otherです。ここで、nself / otherの正確な値に最も近い整数であり、2つの整数が等しく近い場合は、偶数が選択されます。

結果がゼロの場合、その符号は self の符号になります。

>>> Decimal(18).remainder_near(Decimal(10))
Decimal('-2')
>>> Decimal(25).remainder_near(Decimal(10))
Decimal('5')
>>> Decimal(35).remainder_near(Decimal(10))
Decimal('-5')
rotate(other, context=None)

第1オペランドの桁を第2オペランドで指定された量だけローテーションした結果を返します。 2番目のオペランドは、-precisionからprecisionまでの範囲の整数である必要があります。 第2オペランドの絶対値は、回転する場所の数を示します。 2番目のオペランドが正の場合、回転は左になります。 それ以外の場合、回転は右になります。 最初のオペランドの係数は、必要に応じて長さの精度を上げるために左側にゼロが埋め込まれます。 第1オペランドの符号と指数は変更されていません。

same_quantum(other, context=None)

自己と他の指数が同じであるかどうか、または両方がNaNであるかどうかをテストします。

この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めも実行されません。 例外として、第2オペランドを正確に変換できない場合、CバージョンはInvalidOperationを発生させる可能性があります。

scaleb(other, context=None)

指数を2番目に調整した最初のオペランドを返します。 同様に、10**otherを掛けた最初のオペランドを返します。 2番目のオペランドは整数でなければなりません。

shift(other, context=None)

第1オペランドの桁を第2オペランドで指定した量だけシフトした結果を返します。 2番目のオペランドは、-precisionからprecisionまでの範囲の整数である必要があります。 第2オペランドの絶対値は、シフトする場所の数を示します。 2番目のオペランドが正の場合、シフトは左になります。 それ以外の場合、シフトは右になります。 係数にシフトされた桁はゼロです。 第1オペランドの符号と指数は変更されていません。

sqrt(context=None)

引数の平方根を完全な精度で返します。

to_eng_string(context=None)

指数が必要な場合は、工学的記数法を使用して文字列に変換します。

工学的記数法には、3の倍数である指数があります。 これにより、小数点以下3桁まで残される可能性があり、1つまたは2つの後続ゼロの追加が必要になる場合があります。

たとえば、これはDecimal('123E+1')Decimal('1.23E+3')に変換します。

to_integral(rounding=None, context=None)

to_integral_value()メソッドと同じです。 to_integralの名前は、古いバージョンとの互換性のために保持されています。

to_integral_exact(rounding=None, context=None)

最も近い整数に丸め、丸めが発生した場合は、必要に応じて Inexact または Rounded を通知します。 丸めモードは、指定されている場合はroundingパラメーターによって決定され、指定されていない場合は指定されたcontextによって決定されます。 どちらのパラメーターも指定されていない場合は、現在のコンテキストの丸めモードが使用されます。

to_integral_value(rounding=None, context=None)

Inexact または Rounded を通知せずに最も近い整数に丸めます。 指定されている場合は、丸めを適用します。 それ以外の場合は、提供されたコンテキストまたは現在のコンテキストのいずれかで丸め方法を使用します。

論理オペランド

logical_and()logical_invert()logical_or()、およびlogical_xor()メソッドは、引数が論理オペランドであることを想定しています。 論理オペランドは、指数と符号が両方ともゼロで、数字がすべて0または1Decimal インスタンスです。


コンテキストオブジェクト

コンテキストは、算術演算の環境です。 これらは、精度を管理し、丸めのルールを設定し、どの信号を例外として処理するかを決定し、指数の範囲を制限します。

各スレッドには、 getcontext()および setcontext()関数を使用してアクセスまたは変更される独自の現在のコンテキストがあります。

decimal.getcontext()
アクティブなスレッドの現在のコンテキストを返します。
decimal.setcontext(c)
アクティブなスレッドの現在のコンテキストを c に設定します。

with ステートメントと localcontext()関数を使用して、アクティブなコンテキストを一時的に変更することもできます。

decimal.localcontext(ctx=None)

withステートメントへのエントリ時にアクティブスレッドの現在のコンテキストを ctx のコピーに設定し、withステートメントを終了するときに前のコンテキストを復元するコンテキストマネージャを返します。 コンテキストが指定されていない場合は、現在のコンテキストのコピーが使用されます。

たとえば、次のコードは、現在の小数点以下の桁数を42桁に設定し、計算を実行してから、前のコンテキストを自動的に復元します。

from decimal import localcontext

with localcontext() as ctx:
    ctx.prec = 42   # Perform a high precision calculation
    s = calculate_something()
s = +s  # Round the final result back to the default precision

以下で説明する Context コンストラクターを使用して、新しいコンテキストを作成することもできます。 さらに、このモジュールは3つの事前に作成されたコンテキストを提供します。

class decimal.BasicContext

これは、General Decimal ArithmeticSpecificationによって定義された標準コンテキストです。 精度は9に設定されています。 丸めは ROUND_HALF_UP に設定されます。 すべてのフラグがクリアされます。 InexactRounded 、および Subnormal を除くすべてのトラップが有効になります(例外として扱われます)。

トラップの多くが有効になっているため、このコンテキストはデバッグに役立ちます。

class decimal.ExtendedContext

これは、General Decimal ArithmeticSpecificationによって定義された標準コンテキストです。 精度は9に設定されています。 丸めは ROUND_HALF_EVEN に設定されます。 すべてのフラグがクリアされます。 トラップは有効になっていません(計算中に例外が発生しないようにするため)。

トラップが無効になっているため、このコンテキストは、例外を発生させるのではなく、結果値をNaNまたはInfinityにすることを好むアプリケーションに役立ちます。 これにより、アプリケーションは、プログラムを停止するような状況で実行を完了することができます。

class decimal.DefaultContext

このコンテキストは、 Context コンストラクターによって新しいコンテキストのプロトタイプとして使用されます。 フィールド(このような精度)を変更すると、 Context コンストラクターによって作成された新しいコンテキストのデフォルトが変更されます。

このコンテキストは、マルチスレッド環境で最も役立ちます。 スレッドが開始される前にフィールドの1つを変更すると、システム全体のデフォルトを設定する効果があります。 スレッドの開始後にフィールドを変更すると、競合状態を防ぐためにスレッドの同期が必要になるため、お勧めしません。

シングルスレッド環境では、このコンテキストをまったく使用しないことが望ましいです。 代わりに、以下で説明するように、コンテキストを明示的に作成するだけです。

デフォルト値はprec = 28rounding = ROUND_HALF_EVEN で、オーバーフロー、無効操作[ X141X]、および DivisionByZero

提供されている3つのコンテキストに加えて、 Context コンストラクターを使用して新しいコンテキストを作成できます。

class decimal.Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)

新しいコンテキストを作成します。 フィールドが指定されていないか、 None の場合、デフォルト値は DefaultContext からコピーされます。 flags フィールドが指定されていないか、 None の場合、すべてのフラグがクリアされます。

prec は、[1MAX_PREC ]の範囲の整数であり、コンテキストでの算術演算の精度を設定します。

丸めオプションは、丸めモードのセクションにリストされている定数の1つです。

traps および flags フィールドには、設定する信号が一覧表示されます。 一般に、新しいコンテキストはトラップを設定し、フラグをクリアのままにしておく必要があります。

Emin および Emax フィールドは、指数に許容される外側の制限を指定する整数です。 Emin は、[ MIN_EMIN0]、 Emax の範囲で、[0の範囲内である必要があります。 MAX_EMAX ]。

Capitals フィールドは、0または1(デフォルト)のいずれかです。 1に設定すると、指数は大文字のEで出力されます。 それ以外の場合は、小文字のeが使用されます:Decimal('6.02e+23')

クランプフィールドは、0(デフォルト)または1のいずれかです。 1に設定すると、このコンテキストで表現できる Decimal インスタンスの指数eは、Emin - prec + 1 <= e <= Emax - prec + 1の範囲に厳密に制限されます。 クランプ0の場合、より弱い条件が成立します。 Decimal インスタンスの調整済み指数は最大でEmaxです。 クランプ1の場合、指数の制約に合わせるために、可能な場合、正規数が大きいと指数が減少し、対応する数のゼロが係数に追加されます。 これにより、数値の値は保持されますが、重要な後続ゼロに関する情報は失われます。 例えば:

>>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999')
Decimal('1.23000E+999')

クランプの値1により、IEEE754で指定されている固定幅の10進交換形式との互換性が得られます。

Context クラスは、いくつかの汎用メソッドと、特定のコンテキストで直接算術演算を実行するための多数のメソッドを定義します。 さらに、上記の Decimal メソッドのそれぞれ(adjusted()およびas_tuple()メソッドを除く)には、対応する Context メソッドがあります。 。 たとえば、 Context インスタンスCおよび Decimal インスタンスxの場合、C.exp(x)x.exp(context=C)と同等です。 。 各 Context メソッドは、Decimalインスタンスが受け入れられる場所であればどこでもPython整数( int のインスタンス)を受け入れます。

clear_flags()

すべてのフラグを0にリセットします。

clear_traps()

すべてのトラップを0にリセットします。

バージョン3.3の新機能。

copy()

コンテキストの複製を返します。

copy_decimal(num)

Decimalインスタンスnumのコピーを返します。

create_decimal(num)

num から新しいDecimalインスタンスを作成しますが、コンテキストとして self を使用します。 Decimal コンストラクターとは異なり、コンテキストの精度、丸め方法、フラグ、およびトラップが変換に適用されます。

定数はアプリケーションで必要とされるよりも高い精度で与えられることが多いため、これは便利です。 もう1つの利点は、丸めにより、現在の精度を超える桁からの意図しない影響が即座に排除されることです。 次の例では、丸められていない入力を使用すると、合計にゼロを追加すると結果が変わる可能性があります。

>>> getcontext().prec = 3
>>> Decimal('3.4445') + Decimal('1.0023')
Decimal('4.45')
>>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023')
Decimal('4.44')

このメソッドは、IBM仕様のto-number操作を実装します。 引数が文字列の場合、先頭または末尾の空白またはアンダースコアは許可されません。

create_decimal_from_float(f)

float f から新しいDecimalインスタンスを作成しますが、コンテキストとして self を使用して丸めます。 Decimal.from_float()クラスメソッドとは異なり、コンテキスト精度、丸めメソッド、フラグ、およびトラップが変換に適用されます。

>>> context = Context(prec=5, rounding=ROUND_DOWN)
>>> context.create_decimal_from_float(math.pi)
Decimal('3.1415')
>>> context = Context(prec=5, traps=[Inexact])
>>> context.create_decimal_from_float(math.pi)
Traceback (most recent call last):
    ...
decimal.Inexact: None

バージョン3.1の新機能。

Etiny()

Emin - prec + 1に等しい値を返します。これは、正常以下の結果の最小指数値です。 アンダーフローが発生すると、指数は Etiny に設定されます。

Etop()

Emax - prec + 1に等しい値を返します。

小数を操作する通常のアプローチは、小数インスタンスを作成してから、アクティブなスレッドの現在のコンテキスト内で実行される算術演算を適用することです。 別のアプローチは、特定のコンテキスト内で計算するためにコンテキストメソッドを使用することです。 メソッドは Decimal クラスのメソッドと似ており、ここでは簡単に説明します。

abs(x)

x の絶対値を返します。

add(x, y)

xy の合計を返します。

canonical(x)

同じDecimalオブジェクト x を返します。

compare(x, y)

xy を数値で比較します。

compare_signal(x, y)

2つのオペランドの値を数値的に比較します。

compare_total(x, y)

抽象表現を使用して2つのオペランドを比較します。

compare_total_mag(x, y)

符号を無視して、抽象表現を使用して2つのオペランドを比較します。

copy_abs(x)

符号を0に設定した x のコピーを返します。

copy_negate(x)

符号を反転した x のコピーを返します。

copy_sign(x, y)

符号を y から x にコピーします。

divide(x, y)

xy で割った値を返します。

divide_int(x, y)

xy で割った値を返し、整数に切り捨てます。

divmod(x, y)

2つの数値を除算し、結果の整数部分を返します。

exp(x)

e ** x を返します。

fma(x, y, z)

xy を掛けたものに z を掛けたものを返します。

is_canonical(x)

x が正規の場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_finite(x)

x が有限の場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_infinite(x)

x が無限大の場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_nan(x)

x がqNaNまたはsNaNの場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_normal(x)

x が正規数の場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_qnan(x)

x がクワイエットNaNの場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_signed(x)

x が負の場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_snan(x)

x がシグナリングNaNの場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_subnormal(x)

x が正常でない場合、Trueを返します。 それ以外の場合は、Falseを返します。

is_zero(x)

x がゼロの場合、Trueを返します。 それ以外の場合は、Falseを返します。

ln(x)

x の自然(底e)対数を返します。

log10(x)

x の常用対数を返します。

logb(x)

オペランドのMSDの大きさの指数を返します。

logical_and(x, y)

各オペランドの桁の間に論理演算を適用します。

logical_invert(x)

x のすべての桁を反転します。

logical_or(x, y)

各オペランドの桁の間に論理演算またはを適用します。

logical_xor(x, y)

各オペランドの桁の間に論理演算 xor を適用します。

max(x, y)

2つの値を数値的に比較し、最大値を返します。

max_mag(x, y)

符号を無視して値を数値的に比較します。

min(x, y)

2つの値を数値的に比較し、最小値を返します。

min_mag(x, y)

符号を無視して値を数値的に比較します。

minus(x)

マイナスは、Pythonの単項プレフィックスマイナス演算子に対応します。

multiply(x, y)

xy の積を返します。

next_minus(x)

x より小さい表現可能な最大数を返します。

next_plus(x)

x より大きい表現可能な最小の数値を返します。

next_toward(x, y)

y に向かう方向で、 x に最も近い数値を返します。

normalize(x)

x を最も単純な形式に縮小します。

number_class(x)

x のクラスの表示を返します。

plus(x)

Plusは、Pythonの単項接頭辞plus演算子に対応します。 この操作はコンテキストの精度と丸めを適用するため、ID操作ではありません。

power(x, y, modulo=None)

xyの累乗に戻し、与えられた場合はmoduloを法として減らします。

2つの引数を使用して、x**yを計算します。 xが負の場合、yは整数でなければなりません。 yが整数であり、結果が有限であり、「精度」の桁で正確に表現できない限り、結果は不正確になります。 コンテキストの丸めモードが使用されます。 Pythonバージョンでは、結果は常に正しく丸められます。

Decimal(0) ** Decimal(0)InvalidOperationになり、InvalidOperationがトラップされていない場合は、Decimal('NaN')になります。

バージョン3.3で変更: Cモジュールは、正しく丸められた exp()および ln()に関して power()を計算します。関数。 結果は明確に定義されていますが、「ほとんどの場合、正しく丸められている」だけです。

3つの引数を使用して、(x**y) % moduloを計算します。 3つの引数形式の場合、引数に関する次の制限が適用されます。

  • 3つの引数はすべて整数でなければなりません

  • yは非負でなければなりません

  • xまたはyの少なくとも1つがゼロ以外である必要があります

  • moduloはゼロ以外で、最大で「精度」の桁でなければなりません


Context.power(x, y, modulo)から得られる値は、(x**y) % moduloを無制限の精度で計算することによって得られる値と同じですが、より効率的に計算されます。 xy、およびmoduloの指数に関係なく、結果の指数はゼロです。 結果は常に正確です。

quantize(x, y)

x (四捨五入)に等しい値を返します。指数は y です。

radix()

これは10進数なので、10を返します:)

remainder(x, y)

整数除算の余りを返します。

結果の符号は、ゼロ以外の場合、元の配当の符号と同じです。

remainder_near(x, y)

x - y * nを返します。ここで、 nx / yの正確な値に最も近い整数です(結果が0の場合、その符号は x の符号になります。 ])。

rotate(x, y)

xy 回の回転コピーを返します。

same_quantum(x, y)

2つのオペランドの指数が同じ場合は、Trueを返します。

scaleb(x, y)

expに2番目の値を加算した後、最初のオペランドを返します。

shift(x, y)

xy 回のシフトされたコピーを返します。

sqrt(x)

コンテキストの精度に対する非負数の平方根。

subtract(x, y)

xy の差を返します。

to_eng_string(x)

指数が必要な場合は、工学的記数法を使用して文字列に変換します。

工学的記数法には、3の倍数である指数があります。 これにより、小数点以下3桁まで残される可能性があり、1つまたは2つの後続ゼロの追加が必要になる場合があります。

to_integral_exact(x)

整数に丸めます。

to_sci_string(x)

科学的記数法を使用して数値を文字列に変換します。


定数

このセクションの定数は、Cモジュールにのみ関連します。 これらは、互換性のために純粋なPythonバージョンにも含まれています。

32ビット 64ビット
decimal.MAX_PREC
425000000 999999999999999999
decimal.MAX_EMAX
425000000 999999999999999999
decimal.MIN_EMIN
-425000000 -999999999999999999
decimal.MIN_ETINY
-849999999 -1999999999999999997
decimal.HAVE_THREADS
値はTrueです。 Pythonには常にスレッドがあるため、非推奨になりました。

バージョン3.9以降非推奨。


decimal.HAVE_CONTEXTVAR
デフォルト値はTrueです。 Pythonが--without-decimal-contextvarでコンパイルされている場合、Cバージョンはコルーチンローカルコンテキストではなくスレッドローカルコンテキストを使用し、値はFalseです。 これは、一部のネストされたコンテキストシナリオではわずかに高速です。

バージョン3.9の新機能: 3.7および3.8にバックポート


丸めモード

decimal.ROUND_CEILING
Infinityに向かって丸めます。
decimal.ROUND_DOWN
ゼロに向かって丸めます。
decimal.ROUND_FLOOR
-Infinityに向かって丸めます。
decimal.ROUND_HALF_DOWN
ネクタイがゼロに近づくように、最も近い値に丸めます。
decimal.ROUND_HALF_EVEN
最も近い偶数の整数に同点で四捨五入します。
decimal.ROUND_HALF_UP
ネクタイがゼロから離れる方向に最も近い値に丸めます。
decimal.ROUND_UP
ゼロから四捨五入します。
decimal.ROUND_05UP
ゼロに向かって丸めた後の最後の桁が0または5であった場合は、ゼロから丸めます。 それ以外の場合はゼロに向かって丸めます。


信号

信号は、計算中に発生する条件を表します。 それぞれが1つのコンテキストフラグと1つのコンテキストトラップイネーブラに対応します。

コンテキストフラグは、条件が発生するたびに設定されます。 計算後、情報提供の目的で(たとえば、計算が正確であったかどうかを判断するために)フラグをチェックできます。 フラグを確認した後、次の計算を開始する前に、必ずすべてのフラグをクリアしてください。

コンテキストのトラップイネーブラーがシグナルに設定されている場合、条件によってPython例外が発生します。 たとえば、 DivisionByZero トラップが設定されている場合、条件が発生すると DivisionByZero 例外が発生します。

class decimal.Clamped

表現の制約に合うように指数を変更しました。

通常、クランプは、指数がコンテキストのEminおよびEmaxの制限を超えたときに発生します。 可能であれば、係数にゼロを追加することにより、指数が縮小されて適合します。

class decimal.DecimalException
他の信号の基本クラスと ArithmeticError のサブクラス。
class decimal.DivisionByZero

非無限数をゼロで除算することを通知します。

除算、モジュロ除算、または数値を負のべき乗にするときに発生する可能性があります。 この信号がトラップされていない場合は、計算への入力によって決定された符号でInfinityまたは-Infinityを返します。

class decimal.Inexact

丸めが発生し、結果が正確でないことを示します。

丸め中にゼロ以外の数字が破棄された場合のシグナル。 丸められた結果が返されます。 信号旗またはトラップは、結果が不正確な場合を検出するために使用されます。

class decimal.InvalidOperation

無効な操作が実行されました。

意味のない操作が要求されたことを示します。 トラップされていない場合は、NaNを返します。 考えられる原因は次のとおりです。

Infinity - Infinity
0 * Infinity
Infinity / Infinity
x % 0
Infinity % x
sqrt(-x) and x > 0
0 ** 0
x ** (non-integer)
x ** Infinity
class decimal.Overflow

数値オーバーフロー。

丸めが発生した後、指数がEmaxより大きいことを示します。 トラップされていない場合、結果は丸めモードによって異なり、表現可能な最大の有限数まで内側に引っ張るか、Infinityまで外側に丸めます。 いずれの場合も、 Inexact および Rounded も通知されます。

class decimal.Rounded

情報が失われた可能性はありませんが、丸めが発生しました。

丸めによって数字が破棄されるたびに通知されます。 それらの桁がゼロであっても(5.005.0に丸めるなど)。 トラップされていない場合、結果は変更されずに返されます。 この信号は、有効数字の損失を検出するために使用されます。

class decimal.Subnormal

丸め前の指数はEminよりも低かった。

演算結果が異常(指数が小さすぎる)の場合に発生します。 トラップされていない場合、結果は変更されずに返されます。

class decimal.Underflow

結果がゼロに丸められた数値アンダーフロー。

丸めによって異常な結果がゼロにプッシュされたときに発生します。 Inexact および Subnormal も通知されます。

class decimal.FloatOperation

floatとDecimalsを混合するためのより厳密なセマンティクスを有効にします。

信号がトラップされていない場合(デフォルト)、 Decimal コンストラクター、 create_decimal()、およびすべての比較演算子で、floatとDecimalsの混合が許可されます。 変換と比較はどちらも正確です。 混合操作の発生は、コンテキストフラグで FloatOperation を設定することにより、サイレントに記録されます。 from_float()または create_decimal_from_float()を使用した明示的な変換では、フラグは設定されません。

それ以外の場合(信号はトラップされます)、等式比較と明示的な変換のみがサイレントになります。 他のすべての混合操作は FloatOperation を発生させます。

次の表は、シグナルの階層をまとめたものです。

exceptions.ArithmeticError(exceptions.Exception)
    DecimalException
        Clamped
        DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
        Inexact
            Overflow(Inexact, Rounded)
            Underflow(Inexact, Rounded, Subnormal)
        InvalidOperation
        Rounded
        Subnormal
        FloatOperation(DecimalException, exceptions.TypeError)

浮動小数点ノート

精度を高めて丸め誤差を軽減

10進浮動小数点を使用すると、10進表現エラーが排除されます(0.1を正確に表現できるようになります)。 ただし、ゼロ以外の桁が固定精度を超えると、一部の演算で丸め誤差が発生する可能性があります。

丸め誤差の影響は、ほぼ相殺された量の加算または減算によって増幅され、重要性が失われる可能性があります。 クヌースは、精度が不十分な丸められた浮動小数点演算が加法の結合法則と分配法則の崩壊を引き起こす2つの有益な例を提供します。

# Examples from Seminumerical Algorithms, Section 4.2.2.
>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 8

>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w
Decimal('9.5111111')
>>> u + (v + w)
Decimal('10')

>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w)
Decimal('0.01')
>>> u * (v+w)
Decimal('0.0060000')

10進数モジュールを使用すると、精度を十分に拡張して桁落ちを回避することにより、IDを復元できます。

>>> getcontext().prec = 20
>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w
Decimal('9.51111111')
>>> u + (v + w)
Decimal('9.51111111')
>>>
>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w)
Decimal('0.0060000')
>>> u * (v+w)
Decimal('0.0060000')

特別な値

10進数モジュールの記数法は、NaNsNaN-InfinityInfinity、および2つのゼロ[ X143X] および-0

無限大は、Decimal('Infinity')を使用して直接構築できます。 また、 DivisionByZero 信号がトラップされていない場合、ゼロ除算から発生する可能性があります。 同様に、オーバーフロー信号がトラップされていない場合、表現可能な最大数の制限を超えて丸めることにより、無限大が発生する可能性があります。

無限大は符号付き(アフィン)であり、非常に大きく不確定な数として扱われる算術演算で使用できます。 たとえば、定数を無限大に追加すると、別の無限大の結果が得られます。

一部の操作は不確定でNaNを返すか、 InvalidOperation シグナルがトラップされた場合は、例外を発生させます。 たとえば、0/0NaNを返します。これは、「数値ではない」ことを意味します。 この種類のNaNは静かで、一度作成されると、他の計算を通過し、常に別のNaNになります。 この動作は、入力が欠落していることがある一連の計算に役立ちます。これにより、特定の結果に無効のフラグを付けながら計算を続行できます。

バリエーションはsNaNで、すべての操作の後に静かなままではなく信号を送ります。 これは、無効な結果が特別な処理のために計算を中断する必要がある場合に役立つ戻り値です。

NaNが関係している場合、Pythonの比較演算子の動作は少し驚くかもしれません。 オペランドの1つがクワイエットまたはシグナリングNaNである等式のテストは、常に False を返しますが、不等式のテストは常にを返します。 ] True<<=>、または>=演算子のいずれかを使用して、2つの小数を比較しようとすると、 InvalidOperation シグナルが発生します。どちらのオペランドもNaNであり、この信号がトラップされていない場合は False を返します。 General Decimal Arithmetic仕様は、直接比較の動作を指定していないことに注意してください。 NaNを含む比較のこれらの規則は、IEEE 854標準から取得されました(セクション5.7の表3を参照)。 厳密な標準への準拠を保証するには、代わりにcompare()およびcompare-signal()メソッドを使用してください。

符号付きゼロは、アンダーフローする計算から生じる可能性があります。 それらは、計算がより正確に実行された場合に生じるであろう符号を保持します。 それらの大きさはゼロであるため、正と負の両方のゼロは等しいものとして扱われ、それらの符号は情報を提供します。

明確であるが等しい2つの符号付きゼロに加えて、精度は異なるが値が同等であるゼロのさまざまな表現があります。 これには少し慣れが必要です。 正規化された浮動小数点表現に慣れている目では、次の計算がゼロに等しい値を返すことはすぐにはわかりません。

>>> 1 / Decimal('Infinity')
Decimal('0E-1000026')

スレッドの操作

getcontext()関数は、スレッドごとに異なる Context オブジェクトにアクセスします。 個別のスレッドコンテキストがあるということは、スレッドが他のスレッドに干渉することなく変更(getcontext().prec=10など)を行うことができることを意味します。

同様に、 setcontext()関数は、そのターゲットを現在のスレッドに自動的に割り当てます。

setcontext()getcontext()の前に呼び出されていない場合、 getcontext()は現在のスレッドで使用する新しいコンテキストを自動的に作成します。

新しいコンテキストは、 DefaultContext と呼ばれるプロトタイプコンテキストからコピーされます。 各スレッドがアプリケーション全体で同じ値を使用するようにデフォルトを制御するには、 DefaultContext オブジェクトを直接変更します。 これは、 getcontext()を呼び出すスレッド間で競合状態が発生しないように、スレッドが開始される前に実行する必要があります。 例えば:

# Set applicationwide defaults for all threads about to be launched
DefaultContext.prec = 12
DefaultContext.rounding = ROUND_DOWN
DefaultContext.traps = ExtendedContext.traps.copy()
DefaultContext.traps[InvalidOperation] = 1
setcontext(DefaultContext)

# Afterwards, the threads can be started
t1.start()
t2.start()
t3.start()
 . . .

レシピ

ユーティリティ関数として機能し、 Decimal クラスを操作する方法を示すいくつかのレシピを次に示します。

def moneyfmt(value, places=2, curr='', sep=',', dp='.',
             pos='', neg='-', trailneg=''):
    """Convert Decimal to a money formatted string.

    places:  required number of places after the decimal point
    curr:    optional currency symbol before the sign (may be blank)
    sep:     optional grouping separator (comma, period, space, or blank)
    dp:      decimal point indicator (comma or period)
             only specify as blank when places is zero
    pos:     optional sign for positive numbers: '+', space or blank
    neg:     optional sign for negative numbers: '-', '(', space or blank
    trailneg:optional trailing minus indicator:  '-', ')', space or blank

    >>> d = Decimal('-1234567.8901')
    >>> moneyfmt(d, curr='$')
    '-$1,234,567.89'
    >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
    '1.234.568-'
    >>> moneyfmt(d, curr='$', neg='(', trailneg=')')
    '($1,234,567.89)'
    >>> moneyfmt(Decimal(123456789), sep=' ')
    '123 456 789.00'
    >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
    '<0.02>'

    """
    q = Decimal(10) ** -places      # 2 places --> '0.01'
    sign, digits, exp = value.quantize(q).as_tuple()
    result = []
    digits = list(map(str, digits))
    build, next = result.append, digits.pop
    if sign:
        build(trailneg)
    for i in range(places):
        build(next() if digits else '0')
    if places:
        build(dp)
    if not digits:
        build('0')
    i = 0
    while digits:
        build(next())
        i += 1
        if i == 3 and digits:
            i = 0
            build(sep)
    build(curr)
    build(neg if sign else pos)
    return ''.join(reversed(result))

def pi():
    """Compute Pi to the current precision.

    >>> print(pi())
    3.141592653589793238462643383

    """
    getcontext().prec += 2  # extra digits for intermediate steps
    three = Decimal(3)      # substitute "three=3.0" for regular floats
    lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
    while s != lasts:
        lasts = s
        n, na = n+na, na+8
        d, da = d+da, da+32
        t = (t * n) / d
        s += t
    getcontext().prec -= 2
    return +s               # unary plus applies the new precision

def exp(x):
    """Return e raised to the power of x.  Result type matches input type.

    >>> print(exp(Decimal(1)))
    2.718281828459045235360287471
    >>> print(exp(Decimal(2)))
    7.389056098930650227230427461
    >>> print(exp(2.0))
    7.38905609893
    >>> print(exp(2+0j))
    (7.38905609893+0j)

    """
    getcontext().prec += 2
    i, lasts, s, fact, num = 0, 0, 1, 1, 1
    while s != lasts:
        lasts = s
        i += 1
        fact *= i
        num *= x
        s += num / fact
    getcontext().prec -= 2
    return +s

def cos(x):
    """Return the cosine of x as measured in radians.

    The Taylor series approximation works best for a small value of x.
    For larger values, first compute x = x % (2 * pi).

    >>> print(cos(Decimal('0.5')))
    0.8775825618903727161162815826
    >>> print(cos(0.5))
    0.87758256189
    >>> print(cos(0.5+0j))
    (0.87758256189+0j)

    """
    getcontext().prec += 2
    i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 1
    while s != lasts:
        lasts = s
        i += 2
        fact *= i * (i-1)
        num *= x * x
        sign *= -1
        s += num / fact * sign
    getcontext().prec -= 2
    return +s

def sin(x):
    """Return the sine of x as measured in radians.

    The Taylor series approximation works best for a small value of x.
    For larger values, first compute x = x % (2 * pi).

    >>> print(sin(Decimal('0.5')))
    0.4794255386042030002732879352
    >>> print(sin(0.5))
    0.479425538604
    >>> print(sin(0.5+0j))
    (0.479425538604+0j)

    """
    getcontext().prec += 2
    i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 1
    while s != lasts:
        lasts = s
        i += 2
        fact *= i * (i-1)
        num *= x * x
        sign *= -1
        s += num / fact * sign
    getcontext().prec -= 2
    return +s

10進数のFAQ

NS。 decimal.Decimal('1234.5')と入力するのは面倒です。 インタラクティブインタプリタを使用するときに入力を最小限に抑える方法はありますか?

  1. 一部のユーザーは、コンストラクターを1文字に省略します。

    >>> D = decimal.Decimal
    >>> D('1.23') + D('3.45')
    Decimal('4.68')

NS。 小数点以下2桁の固定小数点アプリケーションでは、一部の入力には多くの桁があり、丸める必要があります。 他のものは、余分な数字を持っているとは考えられておらず、検証する必要があります。 どのような方法を使用する必要がありますか?

NS。 quantize()メソッドは、固定の小数点以下の桁数に丸められます。 Inexact トラップが設定されている場合、検証にも役立ちます。

>>> TWOPLACES = Decimal(10) ** -2       # same as Decimal('0.01')
>>> # Round to two places
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
>>> # Validate that a number does not exceed two places
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
   ...
Inexact: None

NS。 有効な2つの場所の入力を取得したら、アプリケーション全体でその不変条件を維持するにはどうすればよいですか?

NS。 加算、減算、整数による乗算などの一部の演算では、固定小数点が自動的に保持されます。 除算や非整数乗算などの他の演算では、小数点以下の桁数が変更されるため、quantize()ステップでフォローアップする必要があります。

>>> a = Decimal('102.72')           # Initial fixed-point values
>>> b = Decimal('3.17')
>>> a + b                           # Addition preserves fixed-point
Decimal('105.89')
>>> a - b
Decimal('99.55')
>>> a * 42                          # So does integer multiplication
Decimal('4314.24')
>>> (a * b).quantize(TWOPLACES)     # Must quantize non-integer multiplication
Decimal('325.62')
>>> (b / a).quantize(TWOPLACES)     # And quantize division
Decimal('0.03')

固定小数点アプリケーションの開発では、quantize()ステップを処理する関数を定義すると便利です。

>>> def mul(x, y, fp=TWOPLACES):
...     return (x * y).quantize(fp)
>>> def div(x, y, fp=TWOPLACES):
...     return (x / y).quantize(fp)
>>> mul(a, b)                       # Automatically preserve fixed-point
Decimal('325.62')
>>> div(b, a)
Decimal('0.03')

NS。 同じ値を表現する方法はたくさんあります。 数値200200.0002E2、および02E+4はすべて、さまざまな精度で同じ値を持ちます。 それらを単一の認識可能な標準値に変換する方法はありますか?

NS。 normalize()メソッドは、すべての同等の値を単一の代表にマップします。

>>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
>>> [v.normalize() for v in values]
[Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]

NS。 一部の10進値は、常に指数表記で出力されます。 非指数表現を取得する方法はありますか?

NS。 一部の値では、指数表記が係数の重要な場所の数を表す唯一の方法です。 たとえば、5.0E+35000として表すと、値は一定に保たれますが、元の2桁の重要性を示すことはできません。

アプリケーションが重要度の追跡を気にしない場合、指数と末尾のゼロを削除して重要度を失うのは簡単ですが、値は変更されません。

>>> def remove_exponent(d):
...     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')
  1. 通常のfloatを Decimal に変換する方法はありますか?

NS。 はい、任意の2進浮動小数点数は、正確に10進数として表すことができますが、正確な変換には、直感が示唆するよりも高い精度が必要になる場合があります。

>>> Decimal(math.pi)
Decimal('3.141592653589793115997963468544185161590576171875')

NS。 複雑な計算の中で、精度が不十分であるか丸めの異常が原因で誤った結果が得られていないことを確認するにはどうすればよいですか。

NS。 10進モジュールを使用すると、結果を簡単にテストできます。 ベストプラクティスは、より高い精度とさまざまな丸めモードを使用して計算を再実行することです。 大きく異なる結果は、不十分な精度、丸めモードの問題、悪条件の入力、または数値的に不安定なアルゴリズムを示します。

NS。 コンテキストの精度は操作の結果に適用されますが、入力には適用されないことに気付きました。 異なる精度の値を混合するときに注意すべき点はありますか?

NS。 はい。 原則は、すべての値が正確であると見なされ、それらの値の算術も正確であると見なされることです。 結果のみが四捨五入されます。 入力の利点は、「入力したものが得られるもの」であるということです。 欠点は、入力が丸められていないことを忘れると、結果が奇妙に見える可能性があることです。

>>> getcontext().prec = 3
>>> Decimal('3.104') + Decimal('2.104')
Decimal('5.21')
>>> Decimal('3.104') + Decimal('0.000') + Decimal('2.104')
Decimal('5.20')

解決策は、精度を上げるか、単項プラス演算を使用して入力を強制的に丸めることです。

>>> getcontext().prec = 3
>>> +Decimal('1.23456789')      # unary plus triggers rounding
Decimal('1.23')

または、 Context.create_decimal()メソッドを使用して、作成時に入力を丸めることができます。

>>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal('1.2345')
  1. CPythonの実装は多数に対して高速ですか?

NS。 はい。 CPythonおよびPyPy3の実装では、10進モジュールのC / CFFIバージョンは、高速 libmpdec ライブラリを統合して、任意精度の正しく丸められた10進浮動小数点演算を実現します。 libmpdecは、中規模の数値にはカラツバ乗算を使用し、非常に大きな数値には数値理論変換を使用します。 ただし、このパフォーマンスの向上を実現するには、丸められていない計算のコンテキストを設定する必要があります。

>>> c = getcontext()
>>> c.prec = MAX_PREC
>>> c.Emax = MAX_EMAX
>>> c.Emin = MIN_EMIN

バージョン3.3の新機能。