9.4。 10進数 —10進固定小数点および浮動小数点演算
バージョン2.4の新機能。
decimal モジュールは、10進浮動小数点演算のサポートを提供します。 float データ型に比べていくつかの利点があります。
Decimalは、「人々を念頭に置いて設計された浮動小数点モデルに基づいており、必然的に最も重要なガイド原則があります。コンピューターは、人々が学校で学ぶ算術と同じように機能する算術を提供する必要があります。」 –10進算術仕様からの抜粋。
10進数は正確に表すことができます。 対照的に、
1.1
や2.2
のような数値は、2進浮動小数点で正確に表現されていません。 エンドユーザーは通常、バイナリ浮動小数点の場合のように1.1 + 2.2
が3.3000000000000003
として表示されることを期待しません。正確さは算術に引き継がれます。 10進浮動小数点では、
0.1 + 0.1 + 0.1 - 0.3
は正確にゼロに等しくなります。 バイナリ浮動小数点では、結果は5.5511151231257827e-017
です。 ゼロに近い間、違いは信頼できる同等性テストを妨げ、違いは蓄積する可能性があります。 このため、厳密な等式不変量を持つ会計アプリケーションでは、10進数が推奨されます。小数モジュールには、
1.30 + 1.20
が2.50
になるように、重要な場所の概念が組み込まれています。 末尾のゼロは、重要性を示すために保持されます。 これは、金銭的アプリケーションの通常のプレゼンテーションです。 掛け算の場合、「教科書」アプローチでは、被乗数のすべての数値を使用します。 たとえば、1.3 * 1.2
は1.56
を提供し、1.30 * 1.20
は1.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
、-Infinity
、NaN
などの特別な値も含まれます。 この規格では、-0
と+0
も区別されています。
算術演算のコンテキストは、精度、丸め規則、指数の制限、操作の結果を示すフラグ、および信号を例外として処理するかどうかを決定するトラップイネーブラーを指定する環境です。 丸めオプションには、ROUND_CEILING
、ROUND_DOWN
、ROUND_FLOOR
、ROUND_HALF_DOWN
、ROUND_HALF_EVEN
、ROUND_HALF_UP
、 [X95X ]、およびROUND_05UP
。
信号は、計算の過程で発生する例外的な条件のグループです。 アプリケーションのニーズに応じて、シグナルは無視されるか、情報提供と見なされるか、例外として扱われる場合があります。 10進モジュールの信号は、 Clamped 、 InvalidOperation 、 DivisionByZero 、 Inexact 、 Rounded 、です。 ]異常、オーバーフロー、およびアンダーフロー。
各信号には、フラグとトラップイネーブラーがあります。 信号が検出されると、そのフラグが1に設定され、トラップイネーブラーが1に設定されると、例外が発生します。 フラグはスティッキーであるため、ユーザーは計算を監視する前にフラグをリセットする必要があります。
9.4.1。 クイックスタートチュートリアル
小数の使用の通常の開始は、モジュールをインポートし、 getcontext()で現在のコンテキストを表示し、必要に応じて、精度、丸め、または有効なトラップに新しい値を設定することです。
>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
capitals=1, 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.41421356237')
>>> Decimal(2) ** Decimal('0.5')
Decimal('1.414213562373095048801688724')
>>> Decimal('NaN')
Decimal('NaN')
>>> Decimal('-Infinity')
Decimal('-Infinity')
新しい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')
10進数は、Pythonの他の多くの部分とうまく相互作用します。 これは、小さな10進浮動小数点浮動小数点サーカスです。
>>> data = 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) # round() first converts to binary floating point
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つの標準コンテキスト BasicContext と ExtendedContext を提供します。 前者は、トラップの多くが有効になっているため、デバッグに特に役立ちます。
>>> 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=-999999999, Emax=999999999,
capitals=1, 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=-999999999, Emax=999999999,
capitals=1, flags=[Rounded, Inexact], 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数値型と同じようにデータを操作します。
9.4.2。 10進オブジェクト
- class decimal.Decimal([value[, context]])
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
value がUnicode文字列の場合、
digit
が上に表示されている他のUnicode10進数も許可されます。 これらには、他のさまざまなアルファベットの10進数(たとえば、アラビア数字とデーバナーガリー数字)と、全幅の数字u'\uff10'
からu'\uff19'
が含まれます。value が tuple の場合、符号(
0
は正、1
は負)、の3つのコンポーネントが必要です。数字のタプル、および整数の指数。 たとえば、Decimal((0, (1, 4, 1, 4), -3))
はDecimal('1.414')
を返します。value が float の場合、2進浮動小数点値はロスレスで正確な10進数に変換されます。 この変換には、53桁以上の精度が必要になることがよくあります。 たとえば、
Decimal(float('1.1'))
はDecimal('1.100000000000000088817841970012523233890533447265625')
に変換されます。context の精度は、格納される桁数には影響しません。 これは、値の桁数によってのみ決定されます。 たとえば、
Decimal('3.00000')
は、コンテキストの精度が3つしかない場合でも、5つのゼロすべてを記録します。context 引数の目的は、 value が不正な形式の文字列である場合の対処方法を決定することです。 コンテキストが InvalidOperation をトラップすると、例外が発生します。 それ以外の場合、コンストラクターは値が
NaN
の新しいDecimalを返します。構築されると、 Decimal オブジェクトは不変になります。
バージョン2.6で変更:文字列からDecimalインスタンスを作成するときに、先頭と末尾の空白文字を使用できます。
バージョン2.7で変更:コンストラクターへの引数が float インスタンスとして許可されるようになりました。
10進浮動小数点オブジェクトは、 float や int などの他の組み込み数値型と多くのプロパティを共有します。 通常の数学演算と特別な方法のすべてが適用されます。 同様に、10進オブジェクトは、コピー、ピクルス化、印刷、辞書キーとしての使用、セット要素としての使用、比較、並べ替え、および別のタイプ( float や long など)への強制変換が可能です)。 。
Decimalオブジェクトの算術演算と、整数および浮動小数点数の算術演算には、いくつかの小さな違いがあります。 剰余演算子
%
が10進オブジェクトに適用される場合、結果の符号は除数の符号ではなく、被除数の符号になります。>>> (-7) % 4 1 >>> Decimal(-7) % Decimal(4) Decimal('-3')
整数除算演算子
//
も同様に動作し、通常のIDx == (x // y) * y + x % y
を維持するために、フロアではなく真の商の整数部分(ゼロに向かって切り捨て)を返します。>>> -7 // 4 -2 >>> Decimal(-7) // Decimal(4) Decimal('-1')
%
および//
演算子は、仕様に記載されているように、remainder
およびdivide-integer
操作を(それぞれ)実装します。10進数オブジェクトは、通常、算術演算で浮動小数点数と組み合わせることができません。たとえば、 10進数を浮動小数点数に追加しようとすると、
TypeError
が発生します。 このルールには1つの例外があります。Pythonの比較演算子を使用して、 float インスタンスx
を Decimal インスタンスy
と比較することができます。 この例外がない限り、 Decimal インスタンスと float インスタンスの比較は、リファレンスマニュアルの Expressions セクションで説明されているさまざまなタイプのオブジェクトを比較するための一般的なルールに従います。紛らわしい結果に。バージョン2.7で変更: float インスタンス
x
と Decimal インスタンスy
の比較で、結果に基づく結果が返されるようになりましたx
およびy
の値について。 以前のバージョンでは、x < y
は、 Decimal インスタンスx
および float インスタンスy
に対して同じ(任意の)結果を返しました。標準の数値プロパティに加えて、10進浮動小数点オブジェクトにはいくつかの特殊なメソッドもあります。
- adjusted()
係数の右端の桁をシフトアウトした後、先頭の桁のみが残るまで調整された指数を返します。
Decimal('321e+5').adjusted()
は7を返します。 小数点に対する最上位桁の位置を決定するために使用されます。
- as_tuple()
番号の名前付きタプル表現を返します:
DecimalTuple(sign, digits, exponent)
。バージョン2.6で変更:名前付きタプルを使用します。
- canonical()
引数の正規エンコーディングを返します。 現在、 Decimal インスタンスのエンコーディングは常に正規であるため、この操作は引数を変更せずに返します。
バージョン2.6の新機能。
- compare(other[, context])
2つのDecimalインスタンスの値を比較します。 この操作は、 compare()が整数ではなくDecimalインスタンスを返すことを除いて、通常の比較メソッド
__cmp__()
と同じように動作し、いずれかのオペランドが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])
この操作は、すべてのNaNが信号を送ることを除いて、 compare()メソッドと同じです。 つまり、どちらのオペランドもシグナリングNaNでない場合、クワイエットNaNオペランドは、シグナリングNaNであるかのように扱われます。
バージョン2.6の新機能。
- compare_total(other)
数値ではなく抽象表現を使用して、2つのオペランドを比較します。 compare()メソッドに似ていますが、結果は Decimal インスタンスの全順序付けになります。 数値は同じで表現が異なる2つの Decimal インスタンスは、次の順序で等しくありません。
>>> Decimal('12.0').compare_total(Decimal('12')) Decimal('-1')
静かで信号を送るNaNも注文全体に含まれます。 この関数の結果は、両方のオペランドが同じ表現の場合は
Decimal('0')
、最初のオペランドが2番目のオペランドよりも全順序で低い場合はDecimal('-1')
、最初のオペランドの場合はDecimal('1')
です。オペランドは、2番目のオペランドよりも全順序で上位にあります。 全注文の詳細については、仕様を参照してください。バージョン2.6の新機能。
- compare_total_mag(other)
compare_total()のように値ではなく抽象表現を使用して、2つのオペランドを比較しますが、各オペランドの符号は無視します。
x.compare_total_mag(y)
はx.copy_abs().compare_total(y.copy_abs())
と同等です。バージョン2.6の新機能。
- conjugate()
自己を返すだけです。このメソッドは、10進仕様に準拠するためだけのものです。
バージョン2.6の新機能。
- copy_abs()
引数の絶対値を返します。 この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めも実行されません。
バージョン2.6の新機能。
- copy_negate()
引数の否定を返します。 この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めも実行されません。
バージョン2.6の新機能。
- copy_sign(other)
符号が第2オペランドの符号と同じになるように設定された第1オペランドのコピーを返します。 例えば:
>>> Decimal('2.3').copy_sign(Decimal('-1.5')) Decimal('-2.3')
この操作はコンテキストの影響を受けず、静かです。フラグは変更されず、丸めも実行されません。
バージョン2.6の新機能。
- exp([context])
指定された数の(自然な)指数関数
e**x
の値を返します。 結果は、ROUND_HALF_EVEN
丸めモードを使用して正しく丸められます。>>> Decimal(1).exp() Decimal('2.718281828459045235360287471') >>> Decimal(321).exp() Decimal('2.561702493119680037517373933E+139')
バージョン2.6の新機能。
- from_float(f)
浮動小数点数を正確に10進数に変換するClassmethod。
注 Decimal.from_float(0.1)は、 Decimal( '0.1')と同じではありません。 0.1はバイナリ浮動小数点で正確に表現できないため、値は 0x1.999999999999ap-4 である最も近い表現可能な値として格納されます。 10進数での同等の値は 0.1000000000000000055511151231257827021181583404541015625 です。
>>> 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')
バージョン2.7の新機能。
- fma(other, third[, context])
融合乗算-加算。 中間製品self * otherを丸めずに、self * other + thirdを返します。
>>> Decimal(2).fma(3, 5) Decimal('11')
バージョン2.6の新機能。
- is_canonical()
引数が正規の場合は True を返し、それ以外の場合は False を返します。 現在、 Decimal インスタンスは常に正規であるため、この操作は常に True を返します。
バージョン2.6の新機能。
- is_normal()
引数が通常の有限の非ゼロ数で、調整された指数が Emin 以上の場合、 True を返します。 引数がゼロ、非正規、無限、またはNaNの場合は、 False を返します。 ここでは、 normal という用語は、正規値を作成するために使用される normalize()メソッドとは異なる意味で使用されていることに注意してください。
バージョン2.6の新機能。
- is_signed()
引数に負の符号がある場合は True を返し、それ以外の場合は False を返します。 ゼロとNaNは両方とも符号を付けることができることに注意してください。
バージョン2.6の新機能。
- is_subnormal()
引数が正常でない場合は True を返し、それ以外の場合は False を返します。 数値が非正規であり、有限であり、調整された指数が Emin 未満の場合は非正規です。
バージョン2.6の新機能。
- ln([context])
オペランドの自然な(基数e)対数を返します。 結果は、
ROUND_HALF_EVEN
丸めモードを使用して正しく丸められます。バージョン2.6の新機能。
- log10([context])
オペランドの基数10の対数を返します。 結果は、
ROUND_HALF_EVEN
丸めモードを使用して正しく丸められます。バージョン2.6の新機能。
- logb([context])
ゼロ以外の数値の場合、そのオペランドの調整済み指数を Decimal インスタンスとして返します。 オペランドがゼロの場合、
Decimal('-Infinity')
が返され、 DivisionByZero フラグが立てられます。 オペランドが無限大の場合、Decimal('Infinity')
が返されます。バージョン2.6の新機能。
- logical_and(other[, context])
logical_and()は、2つの論理オペランドを使用する論理演算です(論理オペランドを参照)。 結果は、2つのオペランドの桁単位の
and
です。バージョン2.6の新機能。
- logical_invert([context])
logical_invert()は論理演算です。 その結果、オペランドが桁単位で反転します。
バージョン2.6の新機能。
- logical_or(other[, context])
logical_or()は、2つの論理オペランドを使用する論理演算です(論理オペランドを参照)。 結果は、2つのオペランドの桁単位の
or
です。バージョン2.6の新機能。
- logical_xor(other[, context])
logical_xor()は、2つの論理オペランドを使用する論理演算です(論理オペランドを参照)。 結果は、2桁の排他的論理和または2つのオペランドの排他的論理和です。
バージョン2.6の新機能。
- max(other[, context])
max(self, other)
と同様ですが、戻る前にコンテキスト丸めルールが適用され、NaN
値が通知されるか無視されます(コンテキストと、通知するか静かにするかによって異なります)。
- max_mag(other[, context])
max()メソッドに似ていますが、比較はオペランドの絶対値を使用して行われます。
バージョン2.6の新機能。
- min(other[, context])
min(self, other)
と同様ですが、戻る前にコンテキスト丸めルールが適用され、NaN
値が通知されるか無視されます(コンテキストと、通知するか静かにするかによって異なります)。
- min_mag(other[, context])
min()メソッドに似ていますが、比較はオペランドの絶対値を使用して行われます。
バージョン2.6の新機能。
- next_minus([context])
指定されたオペランドよりも小さい、指定されたコンテキスト(またはコンテキストが指定されていない場合は現在のスレッドのコンテキスト)で表現可能な最大数を返します。
バージョン2.6の新機能。
- next_plus([context])
指定されたオペランドよりも大きい、指定されたコンテキスト(またはコンテキストが指定されていない場合は現在のスレッドのコンテキスト)で表現可能な最小数を返します。
バージョン2.6の新機能。
- next_toward(other[, context])
2つのオペランドが等しくない場合は、2番目のオペランドの方向で最初のオペランドに最も近い数値を返します。 両方のオペランドが数値的に等しい場合は、符号が2番目のオペランドの符号と同じになるように設定された最初のオペランドのコピーを返します。
バージョン2.6の新機能。
- normalize([context])
右端の後続ゼロを取り除き、
Decimal('0')
に等しい結果をDecimal('0e0')
に変換して、数値を正規化します。 同値類の属性の正規値を生成するために使用されます。 たとえば、Decimal('32.100')
とDecimal('0.321000e+2')
はどちらも、同等の値Decimal('32.1')
に正規化されます。
- number_class([context])
オペランドのクラスを説明する文字列を返します。 戻り値は、次の10個の文字列のいずれかです。
"-Infinity"
は、オペランドが負の無限大であることを示します。"-Normal"
は、オペランドが負の正規数であることを示します。"-Subnormal"
は、オペランドが負で非正規であることを示します。"-Zero"
は、オペランドが負のゼロであることを示します。"+Zero"
は、オペランドが正のゼロであることを示します。"+Subnormal"
は、オペランドが正で非正規であることを示します。"+Normal"
は、オペランドが正の正規数であることを示します。"+Infinity"
は、オペランドが正の無限大であることを示します。"NaN"
は、オペランドがクワイエットNaN(数値ではない)であることを示します。"sNaN"
は、オペランドがシグナリングNaNであることを示します。
バージョン2.6の新機能。
- quantize(exp[, rounding[, context[, watchexp]]])
四捨五入して第2オペランドの指数をとった後、第1オペランドに等しい値を返します。
>>> Decimal('1.41421356').quantize(Decimal('1.000')) Decimal('1.414')
他の操作とは異なり、量子化操作後の係数の長さが精度よりも大きい場合は、 InvalidOperation が通知されます。 これにより、エラー条件がない限り、量子化された指数が常に右側のオペランドの指数と等しくなることが保証されます。
また、他の操作とは異なり、結果が異常で不正確であっても、量子化はアンダーフローを通知しません。
2番目のオペランドの指数が最初のオペランドの指数よりも大きい場合は、丸めが必要になる場合があります。 この場合、丸めモードは、指定されている場合は
rounding
引数によって決定され、指定されていない場合は指定されたcontext
引数によって決定されます。 どちらの引数も指定されていない場合、現在のスレッドのコンテキストの丸めモードが使用されます。watchexp が設定されている場合(デフォルト)、結果の指数が
Emax
より大きいかEtiny
より小さい場合は常にエラーが返されます。
- radix()
Decimal(10)
を返します。これは、 Decimal クラスがすべての算術演算を行う基数(基数)です。 仕様との互換性のために含まれています。バージョン2.6の新機能。
- remainder_near(other[, context])
self を other で割った余りを返します。 これは、
self % other
とは異なり、剰余の符号はその絶対値を最小化するように選択されます。 より正確には、戻り値はself - n * other
です。ここで、n
はself / 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])
第1オペランドの桁を第2オペランドで指定された量だけローテーションした結果を返します。 2番目のオペランドは、-precisionからprecisionまでの範囲の整数である必要があります。 第2オペランドの絶対値は、回転する場所の数を示します。 2番目のオペランドが正の場合、回転は左になります。 それ以外の場合、回転は右になります。 最初のオペランドの係数は、必要に応じて長さの精度を上げるために左側にゼロが埋め込まれます。 第1オペランドの符号と指数は変更されていません。
バージョン2.6の新機能。
- same_quantum(other[, context])
自己と他の指数が同じであるかどうか、または両方が
NaN
であるかどうかをテストします。
- scaleb(other[, context])
指数を2番目に調整した最初のオペランドを返します。 同様に、
10**other
を掛けた最初のオペランドを返します。 2番目のオペランドは整数でなければなりません。バージョン2.6の新機能。
- shift(other[, context])
第1オペランドの桁を第2オペランドで指定した量だけシフトした結果を返します。 2番目のオペランドは、-precisionからprecisionまでの範囲の整数である必要があります。 第2オペランドの絶対値は、シフトする場所の数を示します。 2番目のオペランドが正の場合、シフトは左になります。 それ以外の場合、シフトは右になります。 係数にシフトされた桁はゼロです。 第1オペランドの符号と指数は変更されていません。
バージョン2.6の新機能。
- sqrt([context])
引数の平方根を完全な精度で返します。
- to_eng_string([context])
指数が必要な場合は、工学的記数法を使用して文字列に変換します。
工学的記数法には、3の倍数である指数があります。 これにより、小数点以下3桁まで残される可能性があり、1つまたは2つの後続ゼロの追加が必要になる場合があります。
たとえば、これは
Decimal('123E+1')
をDecimal('1.23E+3')
に変換します。
- to_integral([rounding[, context]])
to_integral_value()メソッドと同じです。
to_integral
の名前は、古いバージョンとの互換性のために保持されています。
9.4.2.1。 論理オペランド
logical_and()
、logical_invert()
、logical_or()
、およびlogical_xor()
メソッドは、引数が論理オペランドであることを想定しています。 論理オペランドは、指数と符号が両方ともゼロで、数字がすべて0
または1
の Decimal インスタンスです。
9.4.3。 コンテキストオブジェクト
コンテキストは、算術演算の環境です。 これらは、精度を管理し、丸めのルールを設定し、どの信号を例外として処理するかを決定し、指数の範囲を制限します。
各スレッドには、 getcontext()および setcontext()関数を使用してアクセスまたは変更される独自の現在のコンテキストがあります。
- decimal.getcontext()
- アクティブなスレッドの現在のコンテキストを返します。
- decimal.setcontext(c)
- アクティブなスレッドの現在のコンテキストを c に設定します。
Python 2.5以降では、 with ステートメントと localcontext()関数を使用して、アクティブなコンテキストを一時的に変更することもできます。
- decimal.localcontext([c])
withステートメントへのエントリ時にアクティブスレッドの現在のコンテキストを c のコピーに設定し、withステートメントを終了するときに前のコンテキストを復元するコンテキストマネージャを返します。 コンテキストが指定されていない場合は、現在のコンテキストのコピーが使用されます。
バージョン2.5の新機能。
たとえば、次のコードは、現在の小数点以下の桁数を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 with localcontext(BasicContext): # temporarily use the BasicContext print Decimal(1) / Decimal(7) print Decimal(355) / Decimal(113)
以下で説明する Context コンストラクターを使用して、新しいコンテキストを作成することもできます。 さらに、このモジュールは3つの事前に作成されたコンテキストを提供します。
- class decimal.BasicContext
これは、General Decimal ArithmeticSpecificationによって定義された標準コンテキストです。 精度は9に設定されています。 丸めは
ROUND_HALF_UP
に設定されます。 すべてのフラグがクリアされます。 Inexact 、 Rounded 、および Subnormal を除くすべてのトラップが有効になります(例外として扱われます)。トラップの多くが有効になっているため、このコンテキストはデバッグに役立ちます。
- class decimal.ExtendedContext
これは、General Decimal ArithmeticSpecificationによって定義された標準コンテキストです。 精度は9に設定されています。 丸めは
ROUND_HALF_EVEN
に設定されます。 すべてのフラグがクリアされます。 トラップは有効になっていません(計算中に例外が発生しないようにするため)。トラップが無効になっているため、このコンテキストは、例外を発生させるのではなく、結果値を
NaN
またはInfinity
にすることを好むアプリケーションに役立ちます。 これにより、アプリケーションは、プログラムを停止するような状況で実行を完了することができます。
- class decimal.DefaultContext
このコンテキストは、 Context コンストラクターによって新しいコンテキストのプロトタイプとして使用されます。 フィールド(このような精度)を変更すると、 Context コンストラクターによって作成された新しいコンテキストのデフォルトが変更されます。
このコンテキストは、マルチスレッド環境で最も役立ちます。 スレッドが開始される前にフィールドの1つを変更すると、システム全体のデフォルトを設定する効果があります。 スレッドの開始後にフィールドを変更すると、競合状態を防ぐためにスレッドの同期が必要になるため、お勧めしません。
シングルスレッド環境では、このコンテキストをまったく使用しないことが望ましいです。 代わりに、以下で説明するように、コンテキストを明示的に作成するだけです。
デフォルト値は、precision = 28、rounding = ROUND_HALF_EVENであり、Overflow、InvalidOperation、およびDivisionByZeroのトラップが有効になっています。
提供されている3つのコンテキストに加えて、 Context コンストラクターを使用して新しいコンテキストを作成できます。
- class decimal.Context(prec=None, rounding=None, traps=None, flags=None, Emin=None, Emax=None, capitals=1)
新しいコンテキストを作成します。 フィールドが指定されていないか、 None の場合、デフォルト値は DefaultContext からコピーされます。 flags フィールドが指定されていないか、 None の場合、すべてのフラグがクリアされます。
prec フィールドは、コンテキストでの算術演算の精度を設定する正の整数です。
丸めオプションは次のいずれかです。
ROUND_CEILING
(Infinity
に向かって)、ROUND_DOWN
(ゼロに向かって)、ROUND_FLOOR
(-Infinity
に向かって)、ROUND_HALF_DOWN
(同点がゼロに向かう最も近い)、ROUND_HALF_EVEN
(最も近い整数に近いタイで最も近い)、ROUND_HALF_UP
(タイがゼロから離れる方向に最も近い)、またはROUND_UP
(ゼロから離れている)。ROUND_05UP
(ゼロに丸めた後の最後の桁が0または5の場合はゼロから離れ、それ以外の場合はゼロに向かって)
traps および flags フィールドには、設定する信号が一覧表示されます。 一般に、新しいコンテキストはトラップを設定し、フラグをクリアのままにしておく必要があります。
Emin および Emax フィールドは、指数に許容される外側の制限を指定する整数です。
Capitals フィールドは、
0
または1
(デフォルト)のいずれかです。1
に設定すると、指数は大文字のE
で出力されます。 それ以外の場合は、小文字のe
が使用されます:Decimal('6.02e+23')
。バージョン2.6で変更:
ROUND_05UP
丸めモードが追加されました。Context クラスは、いくつかの汎用メソッドと、特定のコンテキストで直接算術演算を実行するための多数のメソッドを定義します。 さらに、上記の Decimal メソッドのそれぞれ(
adjusted()
およびas_tuple()
メソッドを除く)には、対応する Context メソッドがあります。 。 たとえば、 Context インスタンスC
および Decimal インスタンスx
の場合、C.exp(x)
はx.exp(context=C)
と同等です。 。 各 Context メソッドは、Decimalインスタンスが受け入れられる場所であればどこでもPython整数( int または long のインスタンス)を受け入れます。- clear_flags()
すべてのフラグを
0
にリセットします。
- 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): ... Inexact: None
バージョン2.7の新機能。
- Etiny()
Emin - prec + 1
に等しい値を返します。これは、正常以下の結果の最小指数値です。 アンダーフローが発生すると、指数は Etiny に設定されます。
- Etop()
Emax - prec + 1
に等しい値を返します。
小数を操作する通常のアプローチは、小数インスタンスを作成してから、アクティブなスレッドの現在のコンテキスト内で実行される算術演算を適用することです。 別のアプローチは、特定のコンテキスト内で計算するためにコンテキストメソッドを使用することです。 メソッドは Decimal クラスのメソッドと似ており、ここでは簡単に説明します。
- abs(x)
x の絶対値を返します。
- add(x, y)
x と y の合計を返します。
- canonical(x)
同じDecimalオブジェクト x を返します。
- compare(x, y)
x と y を数値で比較します。
- 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)
x を y で割った値を返します。
- divide_int(x, y)
x を y で割った値を返し、整数に切り捨てます。
- divmod(x, y)
2つの数値を除算し、結果の整数部分を返します。
- exp(x)
e ** x を返します。
- fma(x, y, z)
x に y を掛けたものに 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)
x と y の積を返します。
- 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])
x
をy
の累乗に戻し、与えられた場合はmodulo
を法として減らします。2つの引数を使用して、
x**y
を計算します。x
が負の場合、y
は整数でなければなりません。y
が整数であり、結果が有限であり、「精度」の桁で正確に表現できない限り、結果は不正確になります。 結果は、現在のスレッドのコンテキストの丸めモードを使用して、常に正しく丸められる必要があります。3つの引数を使用して、
(x**y) % modulo
を計算します。 3つの引数形式の場合、引数に関する次の制限が適用されます。3つの引数はすべて整数でなければなりません
y
は非負でなければなりませんx
またはy
の少なくとも1つがゼロ以外である必要がありますmodulo
はゼロ以外で、最大で「精度」の桁でなければなりません
Context.power(x, y, modulo)
から得られる値は、(x**y) % modulo
を無制限の精度で計算することによって得られる値と同じですが、より効率的に計算されます。x
、y
、およびmodulo
の指数に関係なく、結果の指数はゼロです。 結果は常に正確です。バージョン2.6での変更:
y
は、x**y
で非整数になる可能性があります。 3引数バージョンのより厳しい要件。
- quantize(x, y)
x (四捨五入)に等しい値を返します。指数は y です。
- radix()
これは10進数なので、10を返します:)
- remainder(x, y)
整数除算の余りを返します。
結果の符号は、ゼロ以外の場合、元の配当の符号と同じです。
- remainder_near(x, y)
x - y * n
を返します。ここで、 n はx / y
の正確な値に最も近い整数です(結果が0の場合、その符号は x の符号になります。 ])。
- rotate(x, y)
x 、 y 回の回転コピーを返します。
- same_quantum(x, y)
2つのオペランドの指数が同じ場合は、
True
を返します。
- scaleb(x, y)
expに2番目の値を加算した後、最初のオペランドを返します。
- shift(x, y)
x 、 y 回のシフトされたコピーを返します。
- sqrt(x)
コンテキストの精度に対する非負数の平方根。
- subtract(x, y)
x と y の差を返します。
- to_eng_string(x)
指数が必要な場合は、工学的記数法を使用して文字列に変換します。
工学的記数法には、3の倍数である指数があります。 これにより、小数点以下3桁まで残される可能性があり、1つまたは2つの後続ゼロの追加が必要になる場合があります。
- to_integral_exact(x)
整数に丸めます。
- to_sci_string(x)
科学的記数法を使用して数値を文字列に変換します。
9.4.4。 信号
信号は、計算中に発生する条件を表します。 それぞれが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 x._rescale( non-integer ) sqrt(-x) and x > 0 0 ** 0 x ** (non-integer) x ** Infinity
- class decimal.Overflow
数値オーバーフロー。
丸めが発生した後、指数が
Emax
より大きいことを示します。 トラップされていない場合、結果は丸めモードによって異なり、表現可能な最大の有限数まで内側に引っ張るか、Infinity
まで外側に丸めます。 いずれの場合も、 Inexact および Rounded も通知されます。
- class decimal.Rounded
情報が失われた可能性はありませんが、丸めが発生しました。
丸めによって数字が破棄されるたびに通知されます。 それらの桁がゼロであっても(
5.00
を5.0
に丸めるなど)。 トラップされていない場合、結果は変更されずに返されます。 この信号は、有効数字の損失を検出するために使用されます。
- class decimal.Subnormal
丸め前の指数は
Emin
よりも低かった。演算結果が異常(指数が小さすぎる)の場合に発生します。 トラップされていない場合、結果は変更されずに返されます。
- class decimal.Underflow
結果がゼロに丸められた数値アンダーフロー。
丸めによって異常な結果がゼロにプッシュされたときに発生します。 Inexact および Subnormal も通知されます。
次の表は、シグナルの階層をまとめたものです。
exceptions.ArithmeticError(exceptions.StandardError)
DecimalException
Clamped
DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
Inexact
Overflow(Inexact, Rounded)
Underflow(Inexact, Rounded, Subnormal)
InvalidOperation
Rounded
Subnormal
9.4.5。 浮動小数点ノート
9.4.5.1。 精度を高めて丸め誤差を軽減
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')
9.4.5.2。 特別な値
10進数モジュールの記数法は、NaN
、sNaN
、-Infinity
、Infinity
、および2つのゼロ[ X143X] および-0
。
無限大は、Decimal('Infinity')
を使用して直接構築できます。 また、 DivisionByZero 信号がトラップされていない場合、ゼロ除算から発生する可能性があります。 同様に、オーバーフロー信号がトラップされていない場合、表現可能な最大数の制限を超えて丸めることにより、無限大が発生する可能性があります。
無限大は符号付き(アフィン)であり、非常に大きく不確定な数として扱われる算術演算で使用できます。 たとえば、定数を無限大に追加すると、別の無限大の結果が得られます。
一部の操作は不確定でNaN
を返すか、 InvalidOperation シグナルがトラップされた場合は、例外を発生させます。 たとえば、0/0
はNaN
を返します。これは、「数値ではない」ことを意味します。 この種類の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-1000000026')
9.4.6。 スレッドの操作
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()
. . .
9.4.7。 レシピ
ユーティリティ関数として機能し、 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 = map(str, digits)
build, next = result.append, digits.pop
if sign:
build(trailneg)
for i in range(places):
build(next() if digits else '0')
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.
>>> 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.
>>> 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
9.4.8。 10進数のFAQ
NS。 decimal.Decimal('1234.5')
と入力するのは面倒です。 インタラクティブインタプリタを使用するときに入力を最小限に抑える方法はありますか?
一部のユーザーは、コンストラクターを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。 同じ値を表現する方法はたくさんあります。 数値200
、200.000
、2E2
、および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+3
を5000
として表すと、値は一定に保たれますが、元の2桁の重要性を示すことはできません。
アプリケーションが重要度の追跡を気にしない場合、指数と末尾のゼロを削除して重要度を失うのは簡単ですが、値は変更されません。
def remove_exponent(d):
'''Remove exponent and trailing zeros.
>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')
'''
return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
通常の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')