
今回は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)
[引数]
桁数について見てみると…
>>> 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 : 上位一桁の値によって切り上げ、切り捨てが決まる
正直、切り上げ、切り捨て、四捨五入くらいを覚えておいて、あとは必要に応じて…というくらいで良さそうです。