以前の記事で、decimalを使用した正確な計算を学びましたが、
decimalにはまだ数値の丸めという便利な機能があります。
今回はその数値の丸めについて一緒に学んでいきましょう。
「数値の丸め」と一言に言っても実はたくさんの種類があります。
一つ一つ理解してマスターしましょう!
pythonの数値の丸めの種類
decimalを使用して実際にできる数値の丸めの種類は、
これだけ豊富に存在します。
それぞれの使い方と具体例を学びましょう。
ROUND_CEILING
ROUND_CEILINGの使い道
ROUND_CEILINGは、「プラス方向への切り上げ」です。
decimalの使い方でやった、contextプロパティの指定で
「プラス方向への切り上げ」ができるようになります。
ROUND_CEILINGの具体例
それでは、10/3の答え、3.33333を例にして
ROUND_CEILINGを使用してみましょう。
import decimal
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_CEILING #有効桁数の所でプラス方向に切り上げ
x=decimal.Decimal('10')/decimal.Decimal('3')
print(x)
decimalを使用するときはimport decimalを忘れないように気を付けてください。
出力結果は、3.334になりましたね?
有効桁数4で、4桁目を「プラス方向へ切り上げ」しているので
3.333333…. ⇒ 3.334となっています。
ちなみに、負の数字にROUND_CEILINGを使用したばあいは、
「切り捨て」のような扱いになります。
具体的には、
-3.33333333… ⇒ -3.333(有効桁数4で指定)
となります。
ROUND_FLOOR
ROUND_FLOORの使い道
次にROUND_FLOORです。
こちらは、「マイナス方向への丸め」になります。
ROUND_CEILINGのちょうど逆といったところですね。
ROUND_FLOORの具体例
同様の例に使用してみると、
import decimal
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_FLOOR #有効桁数の所でマイナス方向に丸め
x=decimal.Decimal('-10')/decimal.Decimal('3')
print(x)
出力結果は、-3.334となります。
正の数字にROUND_FLOORを使用すると、
ちょうどROUND_CEILINGの負の数字と同じように、
「切り捨て」のような処理が行われます。
具体的には、
3.333333…. ⇒ 3.333(有効桁数4)
となります。
ROUND_UP
ROUND_UPの使い道
ROUND_UPは正の数字でも、負の数字でも、
切り上げ処理が行われます。
3.3333…⇒3.334
-3.33333…⇒-3.334
ROUND_CEILINGとROUND_FLOORでは、
正か負かによって「切り捨て」が行われていましたが、
それが無いパターンですね。
ROUND_UPの具体例
なんとなく予想はつくと思いますが、
コードを書いておきます。出力結果は3.334です。
import decimal
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_UP #有効桁数の所でプラス方向に切り上げ
x=decimal.Decimal('10')/decimal.Decimal('3')
print(x)
ROUND_DOWN
ROUND_DOWNの使い道
ROUND_DOWNは、ROUND_UPの逆です。
つまり、正負にかかわらず、有効桁数で切り捨てします。
ROUND_DOWNの具体例
負の数をROUND_DOWNした場合、
import decimal
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_DOWN #有効桁数の所でプラス方向に切り上げ
x=decimal.Decimal('-10')/decimal.Decimal('3')
print(x)
-3.333が出力結果となります。
-10を10として、正の数にしたばあいでも
「切り捨て」の処理をされるので、
3.333が出力されます。
ROUND_HALF_DOWN
ROUND_HALF_DOWNの使い道
ROUND_HALF_DOWNは、有効桁数の末尾が0~5と6~9で
処理が変わります。
具体例を見たほうが早いので、具体例をご覧ください。
ROUND_HALF_DOWNの具体例
ここでは、10から小さい値を引いて切り上げされるのか、
切り捨てされるのか確認します。
import decimal
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_DOWN #有効桁数の所が0~5なら切り捨て
x=decimal.Decimal('10')-decimal.Decimal('0.0006')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_DOWN #有効桁数の所が0~5なら切り捨て
x=decimal.Decimal('10')-decimal.Decimal('0.0005')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_DOWN #有効桁数の所が6~9なら切り上げ
x=decimal.Decimal('10')-decimal.Decimal('0.0004')
print(x)
出力結果は、順に
9.999
9.999
10.00となります。
ですから、有効桁数4とした場合には、
9.9994⇒9.999
9.9995⇒9.999
9.9996⇒10.00
という出力結果となります。
イメージとしては、四捨五入ではなく、五捨六入というイメージでしょうか。
ROUND_HALF_EVEN
ROUND_HALF_EVENの使い道
ROUND_HARLF_EVENは、
先ほどのROUND_HALF_DOWNとは、
有効桁数の末尾が5の時の扱いのみ異なります。
ROUND_HALF_EVENの具体例
先ほどのROUND_HALF_DOWNと同様の具体例で
どうなるか確認してみましょう。
import decimal
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_EVEN #有効桁数の所が0~5なら切り捨て
x=decimal.Decimal('10')-decimal.Decimal('0.0006')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_EVEN #有効桁数の所が0~5なら切り捨て
x=decimal.Decimal('10')-decimal.Decimal('0.0005')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_EVEN #有効桁数の所が6~9なら切り上げ
x=decimal.Decimal('10')-decimal.Decimal('0.0004')
print(x)
出力結果は、順に
9.999
10.00
10.00
なので、ROUND_HALF_DOWNとは、末尾が5の場合のみ異なりました。
ただじつは、このHALF_UPとHALF_DOWN
CEILINGとFLOORの関係のように、
正の数を丸めるか、負の数を丸めるかで挙動が変わりますので、
完全な四捨五入とはいきません。
正の数であれば、ROUND_HALF_EVENが四捨五入になっているのは
確認できましたが…
ROUND_HALF_UP(四捨五入)
ROUND_HALF_UPの使い道
ROUND_HALF_UPは、
ROUND_HALF_DOWNとEVENの四捨五入のみできるようにしたものです。
先ほど、正の数であれば、ROUND_HALF_EVENが
四捨五入になるお話はしましたが、
負の数でも四捨五入になるようにしてあるのが、
このROUND_HALF_UPです。
ROUND_HALF_UPの具体例
例としては、「10から小さい値を引くパターン」と、
「-10から小さい値を足すパターン」の2種類で見ていきましょう。
import decimal
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_UP #有効桁数の所が0~5なら切り捨て
x=decimal.Decimal('10')-decimal.Decimal('0.0006')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_UP #有効桁数の所が0~5なら切り捨て
x=decimal.Decimal('10')-decimal.Decimal('0.0005')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_UP #有効桁数の所が6~9なら切り上げ
x=decimal.Decimal('10')-decimal.Decimal('0.0004')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_UP #有効桁数の所が0~5なら切り捨て
x=decimal.Decimal('-10')+decimal.Decimal('0.0006')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_UP #有効桁数の所が0~5なら切り捨て
x=decimal.Decimal('-10')+decimal.Decimal('0.0005')
print(x)
cont=decimal.getcontext() #decimalのContextプロパティを取得
cont.prec=4 #有効桁数を指定
cont.rounding=decimal.ROUND_HALF_UP #有効桁数の所が6~9なら切り上げ
x=decimal.Decimal('-10')+decimal.Decimal('0.0004')
print(x)
出力結果は、順に
9.999
10.00
10.00
-9.999
-10.00
-10.00
となったので、正の数でも、負の数でも四捨五入されているのがわかります。
まとめ
今回は、decimalを使用した数値の丸めについて学びました。
四捨五入以外にも、切り捨てや切り上げなどの処理が必要になることは
多々あると思います。
そのときに向けてしっかりと違いについて理解しておきましょう。
コメント