Pythonで数値を四捨五入するには
Pythonでは、数値計算に必要な組み込み関数も豊富に用意されています。Pythonはデータ分析で活用されていることから、2進数の処理のみならず10進数の演算も得意です。ここでは、ちょっとした計算で用いる四捨五入について、Pythonの利用方法を学んでいきます。
【参考】:Python
四捨五入の処理の基本的な考え方
四捨五入は、数値計算の端数処理の方法の1つです。ある基準となる桁数に対してその下の桁の値が5以上の場合は値を切り上げ、5未満の場合は切り捨てを行います。
コンピュータの計算では端数処理を「丸める」と言い、丸め方によっては誤差が累積されていくために、計算精度を維持するには有効桁数を維持しながら処理を進めるのが良いでしょう。
Pythonで四捨五入を使うには
Pythonで四捨五入を使うには、最初にround()関数を知っておくと良いでしょう。round()では指定した桁数で値を丸めてくれます。なお、round()関数は、偶数への丸め方式(round to even)を採用しており、単純な四捨五入よりも望ましいとされている方式です。
拡張モジュールNumPyでも同様に考え方に基づきます。
【参考】:Python Docs: round() 【参考】:NumPy Docs: numpy.round()
round()関数の使い方
round()関数は、指定した数値を小数点以下の指定桁数(小数点第1位、小数点第2位など)で丸めた値を返します。第1引数は数値で、第2引数は桁指定を表します。第2引数を指定しない場合は、小数点を含まない整数を返します。使い方は次の通りです。
import math
parm=math.pi
print(parm,':',round(parm))
print(parm,':',round(parm,1))
print(parm,':',round(parm,2))
print(parm,':',round(parm,3))
print(parm,':',round(parm,4))
実行結果は以下の通りです。
3.141592653589793 : 3
3.141592653589793 : 3.1
3.141592653589793 : 3.14
3.141592653589793 : 3.142
3.141592653589793 : 3.1416
第2引数が負の値の場合は、整数の桁数(10の位、100の位など)と解釈して値を丸めます。
parm=123456789
print(parm,':',round(parm))
print(parm,':',round(parm,-1))
print(parm,':',round(parm,-2))
print(parm,':',round(parm,-3))
print(parm,':',round(parm,-4))
print(parm,':',round(parm,-5))
print(parm,':',round(parm,-6))
print(parm,':',round(parm,-7))
実行結果は次の通りです。
123456789 : 123456789
123456789 : 123456790
123456789 : 123456800
123456789 : 123457000
123456789 : 123460000
123456789 : 123500000
123456789 : 123000000
123456789 : 120000000
round()関数の動作を理解する
round()関数は、偶数丸めによって処理を行います。丸める値が5を超える場合は切り上げを行い、5より小さい場合は切り捨てとなります。ちょうど5となる場合は、結果が偶数となるように丸められます。次のコードの結果を見てみましょう。
print(round(0.5))
print(round(1.5))
print(round(2.5))
print(round(3.5))
print(round(4.5))
print(round(5.5))
print(round(6.5))
print(round(7.5))
print(round(8.5))
print(round(9.5))
実行結果は、次のように偶数となるように丸め処理が行われます。学校で学んだ四捨五入とは異なる点を理解しておきましょう。
0
2
2
4
4
6
6
8
8
10
round()関数の注意点
round()関数を小数点以下で丸める際は、注意点があります。round()の計算では、小数点以下の桁数が少し増えただけで近似値はピッタリ5として丸められない場合が出てきます。その場合は、5を超える値は切り上げ、5を下回るものは切り捨てとなります。
次の例を見てみましょう。先の例に似ていますが1桁だけ小数点以下を増やしただけです。
print(round(0.95,1))
print(round(1.05,1))
print(round(1.15,1))
print(round(1.25,1))
print(round(1.35,1))
print(round(1.45,1))
print(round(1.55,1))
print(round(1.65,1))
print(round(1.75,1))
print(round(1.85,1))
print(round(1.95,1))
print(round(2.05,1))
実行結果はすべてが偶数に丸められておらず、近似による5を下回る切り捨てや、5を上回る切り上げが発生したことが分かります。
0.9
1.1
1.1
1.2
1.4
1.4
1.6
1.6
1.8
1.9
1.9
2.0
これはピッタリ5の場合の時だけが偶数丸め処理を行うため、浮動小数点の近似値として近い値でもピッタリ5であると判断されない場合があることを意味します。小数点以下で四捨五入を行う場合は、偶数丸めが行われない場合があることを理解しておきましょう。
【参考】:Python Docs: 浮動小数点演算、その問題と制限
四捨五入を正確に行うには
round()関数で解説したように、四捨五入の丸め処理は浮動小数点の近似値に基づいて処理を行っていたため、結果に食い違いが生じることがありました。
Pythonでは10進固定小数点と10進浮動小数点の演算を正確に行うために、Decimalライブラリを提供しています。Decimalライブラリを使用することで、より正確な演算を行うことができます。
【参考】:Python Docs: 浮動小数点演算、その問題と制限
Decimalモジュールとは
Decimalモジュールとは、10進数で正確な演算を行うためのライブラリを指します。小数点以下の数値は、2進数で近似的に表しているため1/2は0.5、1/4は0.25と正確ですが、0.05や0.025となると四則演算などに近似上の違いが生じてしまいます。
Decimalモジュールは10進演算を正確に行うことが可能で、四捨五入なども行うことができます。
【参考】:Python Docs: 十進固定及び浮動小数点数の算術演算
Decimalモジュールの使い方
Decimalモジュールを使うには、”from decimal import *” でモジュールをインポートします。インスタンスには整数や文字列、浮動小数点数・タプルなどを指定することができます。今回は四捨五入の丸め処理を行うために、quantize()で値を丸めていきます。quanitize()は自作の四捨五入に活用できます。
【参考】:Python Docs: 十進固定及び浮動小数点数の算術演算 【参考】:Python Docs: Decimal.quantize
Decimalモジュールを使ってみる
「round()関数の注意点」で解説した小数点以下の丸め処理の注意点がDecimalモジュールで解消しているか確認していきます。round()関数の場合は、偶数丸めが機能しない場合がありました。
ここでは、Decimalモジュールで10進数を文字列で与えます。丸め処理はquantize()を用いて、ROUND_HALF_EVENを指定し、偶数丸めを行います。
from decimal import *
print(Decimal(str(0.95)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.05)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.15)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.25)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.35)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.45)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.55)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.65)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.75)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.85)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(1.95)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
print(Decimal(str(2.05)).quantize(Decimal('0.1'), ROUND_HALF_EVEN))
実行結果は次の通りで、偶数丸めが正常に行われたことが分かります。
1.0
1.0
1.2
1.2
1.4
1.4
1.6
1.6
1.8
1.8
2.0
2.0
なお、最初のDecimal()モジュールの引数はstr(0.95)などと文字列で値を渡しています。ここでstr()ではなく浮動小数点で引数を渡した場合は、同様の近似値として処理されるため、round()関数と同じ実行結果となります。
Pythonは四捨五入などにも活用可能
Pythonは、ビッグデータ分析など科学技術計算に強みを持っています。10進数演算においても、丸め処理を用途に応じて選択することができるなど多様な使い方が可能です。
数値計算の精度を保ちながら効率的な計算ができるよう、このような端数の丸め処理などについても深い知識を得られるように学ぶことをおすすめします。
編集部オススメコンテンツ
アンドエンジニアへの取材依頼、情報提供などはこちらから