Cou氏の徒然日記

ほのぼの日記ブログです。

Python3の学習 その16 (decimal:10進数計算)

Python

今回はdecimal型について。

 

■ decimalモジュールのDecimalデータ型

プログラムに置いて、小数値の計算というのは、単純に実施するとどうしても誤差が出てしまいます。

pythonでもそれはやはり同じのようです。

>>> a = 0.1
>>> b = 0.2
>>> print(a + b == 0.3)
False

試しに値の比較をしてみても、結果は「False」

一致判定になりません。

 

そのため、decimalモジュールをインポートして、Decimal型を使用してみます。

>>> import decimal
>>> da = decimal.Decimal('0.1')
>>> db = decimal.Decimal('0.2')
>>> dc = decimal.Decimal('0.3')
>>> print(da + db == dc)
True

Decimal型で足し算をして、その結果を比較してみると、こちらの結果は「True」。

Decimal型を使うことで、厳密な数値計算ができるようです。

 

■ Decimalデータ型への指定方法

Decimalデータ型作成時には、数値型(intやfloat)を指定もできますが、こちらで実施するとやはり誤差が出てしまいます。

>>> import decimal
>>> decimal.Decimal(1000) +  decimal.Decimal(0.1)
Decimal('1000.100000000000000005551115')
>>> 
>>> decimal.Decimal(0.1) +  decimal.Decimal(0.1)
Decimal('0.2000000000000000111022302463')

かなり小さい小数値での差異になりますが、それでも、比較すると当然おかしくなるので、これではやはりダメです。

 

そのため、decimalデータ型を作成する場合は、文字列型を引数で渡して指定する必要があるようです。

>>> import decimal
>>> decimal.Decimal('1000') +  decimal.Decimal('0.1')
Decimal('1000.1')
>>> 
>>> decimal.Decimal('0.1') +  decimal.Decimal('0.1')
Decimal('0.2')

こうすると、計算結果も誤差が出ず、期待した通りの値になりました。

 

■ Decimalデータ型の数値の丸め方

Decimal型の数値の丸め方を行うには、「quantize()関数」を使えばよいようです。

 

- Decimal.quantize (exp, rounding=None, context=None)

[引数]

  • exp : 桁数
  • rounding : 丸め方法

桁数について見てみると…

>>> import decimal
>>> d = decimal.Decimal('0.5') 
>>>
>>> e = decimal.Decimal('1')
>>> d.quantize(e)
Decimal('0')
>>>
>>> e = decimal.Decimal('0.1') >>> d.quantize(e) Decimal('0.5')
>>> >>> e = decimal.Decimal('0.01') >>> d.quantize(e) Decimal('0.50')
>>> >>> e = decimal.Decimal('0.001') >>> d.quantize(e) Decimal('0.500')

桁数で指定したところで丸められているのがわかります。

 

続いて、丸め方法について色々と試してみます。

>>> from decimal import *
>>> 
>>> e = decimal.Decimal('1')
>>> d.quantize(e, rounding=ROUND_UP)
Decimal('1')
>>> 
>>> e = decimal.Decimal('1')
>>> d.quantize(e, rounding=ROUND_DOWN)
Decimal('0')
>>> 
>>> e = decimal.Decimal('1')
>>> d.quantize(e, rounding=ROUND_HALF_UP)
Decimal('1')
>>> 
>>> e = decimal.Decimal('1')
>>> d.quantize(e, rounding=ROUND_HALF_DOWN)
Decimal('0')
>>> 
>>> e = decimal.Decimal('1')
>>> d.quantize(e, rounding=ROUND_05UP)
Decimal('1')
  • ROUND_UP : 切り上げ
  • ROUND_DOWN : 切り捨て
  • ROUND_HALF_UP : 四捨五入
  • ROUND_HALF_DOWN : 五捨六入
  • ROUND_05UP : 上位一桁の値によって切り上げ、切り捨てが決まる

 

正直、切り上げ、切り捨て、四捨五入くらいを覚えておいて、あとは必要に応じて…というくらいで良さそうです。