メモ_Pythonで期待通りに四捨五入できない場合

pythonでround関数で小数点以下の数値を 四捨五入しようとすると、正確に計算されないケースがあります。 

Round関数で四捨五入がうまくいかないケースを実際に試してみた結果:

下記の結果は、たしかに2.68ではなく、2.67になります。


f = 2.675
 
print(round(f, 2))

公式ドキュメントにもありますが、

注釈 浮動小数点数に対する round() の振る舞いは意外なものかもしれません: 例えば、 round(2.675, 2) は予想通りの 2.68 ではなく 2.67 を与えます。これはバグではありません: これはほとんどの小数が浮動小数点数で正確に表せないことの結果です。詳しくは 浮動小数点演算、その問題と制限 を参照してください。

バグではなく仕様だそうで、浮動小数点数の内部表現による丸め誤差のため、完全な精度の四捨五入を行うことはできないようです。しかし、実用上、問題ない精度で正確に計算する方法はいくつもあります。

解決法1_decimal モジュールを使う

こうした場合、decimal モジュールを使用して高精度な十進数演算を行うと正確な結果が得られます。以下は、decimal モジュールを使用して四捨五入するコード例です。


from decimal import Decimal, ROUND_HALF_UP

f = Decimal('2.675')
rounded = Decimal(f).quantize(Decimal('0.00'), rounding=ROUND_HALF_UP)
print(rounded)  # 結果: 2.68

解決法2_小数点以下を整数になるまで桁上げする

別の方法として、小数点以下の桁を100倍にして整数値にして、round() 関数を使って整数の丸めを行った後に、100で割る方法があります。100倍というのは、求める小数点以下の有効精度に合わせています。以下はその例です。


f = 2.675
rounded = round(f * 100) / 100
print(rounded)  # 結果: 2.68