float型の数値を処理する時に、四捨五入しなければいけないケースが多々あると思います。
そんな時にround関数を使って実装したところ、ある事に気がつきました。
round関数は四捨五入を正しく処理できない!
# round関数を使った出力 print(round(0.1)) # 出力結果 0 print(round(0.2)) # 出力結果 0 print(round(0.3)) # 出力結果 0 print(round(0.4)) # 出力結果 0 print(round(0.5)) # 出力結果 0 print(round(0.6)) # 出力結果 1 print(round(0.9)) # 出力結果 1
0.1 の小数点第一位を四捨五入しようと思い round関数を使うと、一見すると0.1を0で出力してくれているので四捨五入できているように見えなくもない。
・・・っが、0.5 を出力すると 0 になっている事がわかります。
0.6 に対してround関数を使って出力すると 1 になりますね。
つまり、0.5 である場合は 5 を下げてしまう事がわかります。
これだと正しく四捨五入できないのでエラーやバグの原因になります。
PCは浮動小数点の処理が苦手なので、注意しなければいけませんね。
Pythonの場合、四捨五入を正しく処理する為には標準ライブラリのdecimalモジュールを使う事で解決できました。
from decimal import Decimal, ROUND_HALF_UP # 小数点第一位を四捨五入 print(Decimal(str(0.1)).quantize(Decimal("0"), ROUND_HALF_UP)) # 出力結果 0 print(Decimal(str(0.4)).quantize(Decimal("0"), ROUND_HALF_UP)) # 出力結果 0 print(Decimal(str(0.5)).quantize(Decimal("0"), ROUND_HALF_UP)) # 出力結果 1 # 小数点第二位を四捨五入 print(Decimal(str(0.01)).quantize(Decimal("0.1"), ROUND_HALF_UP)) # 出力結果 0.0 # 小数点第二位を四捨五入 print(Decimal(str(0.05)).quantize(Decimal("0.1"), ROUND_HALF_UP)) # 出力結果 0.1 # 小数点第三位を四捨五入 print(Decimal(str(0.001)).quantize(Decimal("0.01"), ROUND_HALF_UP)) # 出力結果 0.00 # 小数点第三位を四捨五入 print(Decimal(str(0.005)).quantize(Decimal("0.01"), ROUND_HALF_UP)) # 出力結果 0.01
上記のようにdecimalモジュールを使う事で 0.5 が 1 に四捨五入され、0.05 は 0.1 に四捨五入されている事が確認できています。
おかげさまでAC取れました!