10進数小数を取り扱うためのライブラリdecimalを使うと、
10進数を正確に計算できます。
import decimal
decimal.Decimal() # => Decimal('0')
decimal.Decimal(0) # => Decimal('0')
decimal.Decimal('0') # => Decimal('0')
decimal.Decimal('3.141592653589793238462643383279502884197169399375105820974944592')
# => Decimal('3.141592653589793238462643383279502884197169399375105820974944592')
decimal.Decimal('Infinity') # => Decimal('Infinity')
decimal.Decimal('-Infinity') # => Decimal('-Infinity')
decimal.Decimal('NaN') # => Decimal('NaN') 無言 (quiet) NaN (Not a Number)
decimal.Decimal('sNaN') # => Decimal('sNaN') 発信(signaling) NaN
decimal.Decimal('667.4e-13').adjusted() # => -11
decimal.Decimal('2.71828').as_integer_ratio() # => (67957, 25000)
decimal.Decimal('667.4e-13').as_tuple() # => DecimalTuple(sign=0, digits=(6, 6, 7, 4), exponent=-14)
decimal.Decimal('1.23').copy_abs() # => Decimal('1.23')
decimal.Decimal('-1.23').copy_abs() # => Decimal('1.23')
decimal.Decimal('1.23').copy_negate() # => Decimal('-1.23')
decimal.Decimal('-1.23').copy_negate() # => Decimal('1.23')
decimal.Decimal('1.23').copy_sign(decimal.Decimal('0.1')) # => Decimal('1.23')
decimal.Decimal('1.23').copy_sign(decimal.Decimal('-0.1')) # => Decimal('-1.23')
decimal.Decimal('-1.23').copy_sign(decimal.Decimal('0.1')) # => Decimal('1.23')
decimal.Decimal('-1.23').copy_sign(decimal.Decimal('-0.1')) # => Decimal('-1.23')
decimal.Decimal(1).exp() # => Decimal('2.718281828459045235360287471')
decimal.Decimal(2).exp() # => Decimal('7.389056098930650227230427461')
decimal.Decimal.from_float(0.1) # => Decimal('0.1000000000000000055511151231257827021181583404541015625')
decimal.Decimal.from_float(0.25) # => Decimal('0.25')
decimal.Decimal.from_float(float('nan')) # => Decimal('NaN')
decimal.Decimal.from_float(float('inf')) # => Decimal('Infinity')
decimal.Decimal.from_float(float('-inf')) # => Decimal('-Infinity')
decimal.Decimal(3).fma(decimal.Decimal(7), decimal.Decimal(11))
# => Decimal('32') 3*7+11
decimal.Decimal('1').is_finite() # => True
decimal.Decimal('NaN').is_finite() # => False
decimal.Decimal('Infinity').is_finite() # => False
decimal.Decimal('1').is_infinite() # => False
decimal.Decimal('NaN').is_infinite() # => False
decimal.Decimal('Infinity').is_infinite() # => True
decimal.Decimal('1').is_nan() # => False
decimal.Decimal('NaN').is_nan() # => True
decimal.Decimal('sNaN').is_nan() # => True
decimal.Decimal('Infinity').is_nan() # => False
decimal.Decimal('1').is_normal() # => True
decimal.Decimal('NaN').is_normal() # => False
decimal.Decimal('sNaN').is_normal() # => False
decimal.Decimal('Infinity').is_normal() # => False
decimal.Decimal(('0.1E-999999')).is_normal() # => False
decimal.Decimal('1').is_qnan() # => False
decimal.Decimal('NaN').is_qnan() # => True
decimal.Decimal('sNaN').is_qnan() # => False
decimal.Decimal('Infinity').is_qnan() # => False
decimal.Decimal('1').is_signed() # => False
decimal.Decimal('NaN').is_signed() # => False
decimal.Decimal('sNaN').is_signed() # => False
decimal.Decimal('Infinity').is_signed() # => False
decimal.Decimal('-1').is_signed() # => True
decimal.Decimal('-NaN').is_signed() # => True
decimal.Decimal('-sNaN').is_signed() # => True
decimal.Decimal('-Infinity').is_signed() # => True
decimal.Decimal('1').is_snan() # => False
decimal.Decimal('NaN').is_snan() # => False
decimal.Decimal('sNaN').is_snan() # => True
decimal.Decimal('Infinity').is_snan() # => False
decimal.Decimal('1').is_subnormal() # => False
decimal.Decimal('NaN').is_subnormal() # => False
decimal.Decimal('sNaN').is_subnormal() # => False
decimal.Decimal('Infinity').is_subnormal() # => False
decimal.Decimal('0.1E-999999').is_subnormal() # => True
decimal.Decimal('0').is_zero() # => True
decimal.Decimal('+0').is_zero() # => True
decimal.Decimal('-0').is_zero() # => True
decimal.Decimal('1').is_zero() # => False
decimal.Decimal('NaN').is_zero() # => False
decimal.Decimal('sNaN').is_zero() # => False
decimal.Decimal('Infinity').is_zero() # => False
decimal.Decimal('2.718281828').ln() # => Decimal('0.9999999998311266953289851341')
decimal.Decimal('2').log10() # => Decimal('0.3010299956639811952137388947')
decimal.Decimal('100').log10() # => Decimal('2')
decimal.Decimal('Infinity').log10() # => Decimal('Infinity')
decimal.Decimal('2').logb() # => Decimal('0')
decimal.Decimal('100').logb() # => Decimal('2')
decimal.Decimal('Infinity').logb() # => Decimal('Infinity')
decimal.Decimal('1100').logical_and(decimal.Decimal('1010')) # => Decimal('1000')
decimal.Decimal('1010').logical_invert() # => Decimal('1111111111111111111111110101')
decimal.Decimal('1100').logical_or(decimal.Decimal('1010')) # => Decimal('1110')
decimal.Decimal('1100').logical_xor(decimal.Decimal('1010')) # => Decimal('110')
decimal.Decimal('123.4').max(decimal.Decimal('123.5')) # => Decimal('123.5')
decimal.Decimal('123.4').max_mag(decimal.Decimal('-123.5')) # => Decimal('-123.5')
decimal.Decimal('123.4').min(decimal.Decimal('123.5')) # => Decimal('123.4')
decimal.Decimal('123.4').min_mag(decimal.Decimal('-123.5')) # => Decimal('123.4')
decimal.Decimal('123.4').next_minus() # => Decimal('123.3999999999999999999999999')
decimal.Decimal('123.4').next_plus() # => Decimal('123.4000000000000000000000001')
decimal.Decimal('123.4').next_toward(decimal.Decimal('123.5')) # => Decimal('123.4000000000000000000000001')
decimal.Decimal('123.4').next_toward(decimal.Decimal('123.3')) # => Decimal('123.3999999999999999999999999')
decimal.Decimal('0').normalize() # => Decimal('0')
decimal.Decimal('123.4').normalize() # => Decimal('123.4')
decimal.Decimal('123.400').normalize() # => Decimal('123.4')
decimal.Decimal('1.234e2').normalize() # => Decimal('123.4')
decimal.Decimal('0').number_class() # => '+Zero'
decimal.Decimal('+0').number_class() # => '+Zero'
decimal.Decimal('-0').number_class() # => '-Zero'
decimal.Decimal('Infinity').number_class() # => '+Infinity'
decimal.Decimal('-Infinity').number_class() # => '-Infinity'
decimal.Decimal('1.2345').number_class() # => '+Normal'
decimal.Decimal('-1.2345').number_class() # => '-Normal'
decimal.Decimal('0.1E-999999').number_class() # => '+Subnormal'
decimal.Decimal('-0.1E-999999').number_class() # => '-Subnormal'
decimal.Decimal('NaN').number_class() # => 'NaN'
decimal.Decimal('sNaN').number_class() # => 'sNaN'
decimal.Decimal('1.23456789').quantize(decimal.Decimal('1.000')) # => Decimal('1.235')
decimal.Decimal('14').remainder_near(decimal.Decimal('3')) # => Decimal('-1') 14-5*3 = -1
decimal.Decimal('13').remainder_near(decimal.Decimal('3')) # => Decimal('1') 13-4*3 = 1
decimal.Decimal('13').remainder_near(decimal.Decimal('2')) # => Decimal('1') 13-6*2 = 1
decimal.Decimal('15').remainder_near(decimal.Decimal('2')) # => Decimal('-1') 15-8*2 = -1
decimal.Decimal('10101').rotate(decimal.Decimal('0')) # => Decimal('10101')
decimal.Decimal('10101').rotate(decimal.Decimal('1')) # => Decimal('101010')
decimal.Decimal('10101').rotate(decimal.Decimal('2')) # => Decimal('1010100')
decimal.Decimal('10101').rotate(decimal.Decimal('-1')) # => Decimal('1000000000000000000000001010')
decimal.Decimal('1.234e2').same_quantum(decimal.Decimal('567')) # => False
decimal.Decimal('1.23e2').same_quantum(decimal.Decimal('5.67e2')) # => True
decimal.Decimal('1.234e2').same_quantum(decimal.Decimal('567.8')) # => True
decimal.Decimal('NaN').same_quantum(decimal.Decimal('567.8')) # => False
decimal.Decimal('NaN').same_quantum(decimal.Decimal('NaN')) # => True
decimal.Decimal('1.23e2').scaleb(decimal.Decimal('10')) # => Decimal('1.23E+12')
decimal.Decimal('1.23e2').scaleb(decimal.Decimal('1')) # => Decimal('1.23E+3')
decimal.Decimal('1.23e2').scaleb(decimal.Decimal('0')) # => Decimal('123')
decimal.Decimal('1.23e2').scaleb(decimal.Decimal('-1')) # => Decimal('12.3')
decimal.Decimal('1.23e2').shift(decimal.Decimal('10')) # => Decimal('1230000000000')
decimal.Decimal('1.23e2').shift(decimal.Decimal('1')) # => Decimal('1230')
decimal.Decimal('1.23e2').shift(decimal.Decimal('0')) # => Decimal('123')
decimal.Decimal('1.23e2').shift(decimal.Decimal('-1')) # => Decimal('12')
decimal.Decimal('25').sqrt() # => Decimal('5')
decimal.Decimal('2').sqrt() # => Decimal('1.414213562373095048801688724')
decimal.Decimal('123456789123.456789').to_eng_string() # => '123456789123.456789'
decimal.Decimal('1.23456789123456789e11').to_eng_string() # => '123456789123.456789'
decimal.Decimal('123e1').to_eng_string() # => '1.23E+3'
decimal.Decimal('12.3e1').to_eng_string() # => '123'
decimal.Decimal('1.23e1').to_eng_string() # => '12.3'
decimal.Decimal('123456789123.456789').to_integral() # => Decimal('123456789123')
decimal.Decimal('123456789123.456789').to_integral_exact() # => Decimal('123456789123')
decimal.Decimal('123456789123.456789').to_integral_value() # => Decimal('123456789123')
decimalの計算では、コンテキストというオブジェクトに保存されている有効桁数などの環境情報が参照されている。
Contextを変更することで有効桁数等の指定を変更できる。
また、計算時に丸めや有効精度落ちなどが発生した場合「フラグ(flags)」に設定がされるようになっている。
「トラップ(traps)」という属性もあり、こちらはシグナル発生時にエラーとするかの設定に使う。
(例えば、trapsDivisionByZeroのトラップを有効にすると0除算でエラーとなり、
トラップを無効にするとエラーとならずDecimal('Infinity')やDecimal('-Infinity')が返却される)
# decimal.Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)
# prec 算術演算の計算精度
# rounding 丸めモード
# traps 捕まえたいシグナル
# flags コンテキストで送出されたシグナル
# Emin 指数の下限
# Emax 指数の上限
# capitals 指数表記の大文字小文字 0(デフォルト):大文字E 0:小文字e
# clamp 指数範囲の設定
decimal.Context()
decimal.Context(prec=10)
## デバッグ用
## 精度9桁、丸め規則ROUND_HALF_UP、エラートラップはInexact, Rounded, Subnormal以外有効
decimal.BasicContext
# => Context(prec=9, rounding=ROUND_HALF_UP, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[Clamped, InvalidOperation, DivisionByZero, Overflow, Underflow])
## エラー送出なし停止させたくないプログラム用
## 精度9桁、丸め規則ROUND_HALF_EVEN、エラートラップは全て無効
decimal.ExtendedContext
# => Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[])
## 多重スレッド環境用
## 精度28桁、丸め規則ROUND_HALF_EVEN、エエラートラップはOverflow, InvalidOperation, DivisionByZeroが有効
## decimal.Contextコンストラクタ仕様時の雛形
decimal.DefaultContext
# => Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
context = decimal.getcontext()
context = decimal.Context()
decimal.setcontext(context)
print(decimal.getcontext().prec) # => 28
with decimal.localcontext() as ctx:
ctx.prec = 30
print(ctx.prec) # => 30
print(decimal.getcontext().prec) # => 30
print(decimal.getcontext().prec) # => 28
# copy() コンテキストの複製
context = decimal.ExtendedContext.copy()
context
# => Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[])
# コンテキスト設定
decimal.setcontext(context)
# 0除算のフラグ確認
context.flags[decimal.DivisionByZero] # => False
# create_decimal_from_float(f) 浮動小数点数fからDecimalインスタンス生成
decimal_zero = decimal.Decimal('0')
# DivisionByZero発生のため指数計算
decimal_zero.logb() # => Decimal('-Infinity')
# 0除算のフラグ確認
context.flags[decimal.DivisionByZero] # => True
# clear_flags() フラグを全て0にリセット
context.clear_flags()
# 0除算のフラグ確認
context.flags[decimal.DivisionByZero] # => False
# トラップ追加
context.traps[decimal.DivisionByZero]= True
## コンテキスト確認
context
# => Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[])
# DivisionByZero発生のため指数計算
try:
decimal_zero.logb() # => DivisionByZero エラー発生
except Exception as e:
print(e)
## コンテキスト確認
context
# => Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[DivisionByZero], traps=[DivisionByZero])
# clear_traps() トラップを全て 0 にリセット
context.clear_traps()
# clear_flags() フラグを全て0にリセット
context.clear_flags()
# DivisionByZero発生のため指数計算
try:
decimal_zero.logb() # => Decimal('-Infinity') エラーなし
except Exception as e:
print(e)
## コンテキスト確認
context
# => Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[DivisionByZero], traps=[])
decimal.Contxtのメソッドcreate_decimal、copy_decimalは
コンテキストの環境情報に応じたDecimal値を返却する。
context = decimal.ExtendedContext.copy()
context
# => Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[])
# コンテキスト設定
decimal.setcontext(context)
# create_decimal(num) コンテキスト使用してDecimalインスタンス生成
d1 = context.create_decimal(123.45)
d1 #= > Decimal('123.4500000000000028421709430')
# copy_decimal(num) Decimalインスタンスnumコピー
d2 = context.copy_decimal(d1)
d2 # => Decimal('123.450000')
context = decimal.Context(prec=10)
context
# => Context(prec=10, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
# コンテキスト設定
decimal.setcontext(context)
# create_decimal(num) コンテキスト使用してDecimalインスタンス生成
d1 = context.create_decimal(123.45)
d1 #= > Decimal('123.4500000')
# copy_decimal(num) Decimalインスタンスnumコピー
d2 = context.copy_decimal(d1)
d2 # => Decimal('123.4500000')
フラグやトラップに指定できるエラー条件は以下の通り。
コンテキストのroundingに設定できる丸めの種類は次の通り。
各種計算を行うDecimalのメソッドとほぼ同様のものがContextにも定義されている。
計算はコンテキストの有効桁数やフラグ設定を参照して行われる。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント