Pythonで小数点以下を切り捨て・切り上げ: math.floor(), math.ceil()
Pythonで浮動小数点数floatの小数点以下を切り捨て・切り上げするには、標準ライブラリmathモジュールのfloor(), ceil()を使う。
なお、厳密にはmath.floor()は「負の無限大への丸め」、math.ceil()は「正の無限大への丸め」となる。負の値を処理する際は注意。
先に結果をまとめておくと以下の通り。「0への丸め」にはint()を使えるが、「無限大への丸め」については関数を定義する必要がある。詳細は後述。
print(math.floor(10.123))
# 10
print(math.floor(-10.123))
# -11
print(math.ceil(10.123))
# 11
print(math.ceil(-10.123))
# -10
print(int(10.123))
# 10
print(int(-10.123))
# -10
また、四捨五入には組み込み関数round()や標準ライブラリdecimalのquantize()を使う。詳細は以下の記事を参照。
NumPy配列ndarrayの要素に対して小数点以下の切り捨て・切り上げをしたい場合は以下の記事を参照。
小数点以下を切り捨て: math.floor()
小数点以下を切り捨てるにはmath.floor()を使う。整数intが返される。
import math
print(math.floor(10.123))
# 10
print(math.floor(10.987))
# 10
print(type(math.floor(10.123)))
# <class 'int'>
整数intの場合は値がそのまま返される。文字列strなど、特殊メソッド__floor__()が定義されていないクラスのオブジェクトはエラーとなる。
print(math.floor(10))
# 10
# print(math.floor('10'))
# TypeError: must be real number, not str
print(hasattr(10, '__floor__'))
# True
print(hasattr('10', '__floor__'))
# False
math.floor(x)が返すのは「xの『床』(x以下の最大の整数)」であり、「負の無限大への丸め (rounding toward minus infinity; RM)」となるため、負の値に対しては以下のような結果となる。
print(math.floor(-10.123))
# -11
print(math.floor(-10.987))
# -11
符号はそのままで絶対値を切り捨てたい、すなわち「0への丸め (rounding toward zero; RZ)」を実現したい場合はint()を使う。後述。
小数点以下を切り上げ: math.ceil()
小数点以下を切り上げるにはmath.ceil()を使う。整数intが返される。
import math
print(math.ceil(10.123))
# 11
print(math.ceil(10.987))
# 11
print(type(math.ceil(10.123)))
# <class 'int'>
整数intの場合は値がそのまま返される。文字列strなど、特殊メソッド__ceil__()が定義されていないクラスのオブジェクトはエラーとなる。
print(math.ceil(10))
# 10
# print(math.ceil('10'))
# TypeError: must be real number, not str
print(hasattr(10, '__ceil__'))
# True
print(hasattr('10', '__ceil__'))
# False
math.ceil(x)が返すのは「xの『天井』(x以上の最小の整数)」であり、「正の無限大への丸め (rounding toward plus infinity; RP)」となるため、負の値に対しては以下のような結果となる。
print(math.ceil(-10.123))
# -10
print(math.ceil(-10.987))
# -10
符号はそのままで絶対値を切り上げたい、すなわち「無限大への丸め (rounding toward infinity; RI)」を実現したい場合については新たな関数を定義する必要がある。後述。
math.floor()とint()との違い
小数点以下の切り捨てにはint()を使うことも可能。
正の数値に対してはmath.floor()と同じ結果を返す。返り値は整数int。
print(int(10.123))
# 10
print(int(10.987))
# 10
print(int(10))
# 10
print(type(int(10.123)))
# <class 'int'>
負の数値に対してはmath.floor()と結果が異なる。
math.floor()が「負の無限大への丸め (rounding toward minus infinity; RM)」であるのに対し、int()は「0への丸め (rounding toward zero; RZ)」となる。int()では常に0に近づく方に丸められる。
print(int(-10.123))
# -10
print(int(-10.987))
# -10
そのほか、int()は文字列strも処理できる。小数を表す文字列は変換できないが、第二引数baseを指定することで2進数や16進数表記の整数の文字列を変換することもできる。
print(int('10'))
# 10
# print(int('10.123'))
# ValueError: invalid literal for int() with base 10: '10.123'
print(int('FF', 16))
# 255
無限大への丸め (rounding toward infinity; RI)
負の値を考慮すると、切り上げ・切り捨ては4種類ある。
上述のように、それぞれ以下の関数で実現できる。
- 負の無限大への丸め:
math.floor() - 正の無限大への丸め:
math.ceil() - 0への丸め:
int() - 無限大への丸め
print(math.floor(10.123))
# 10
print(math.floor(-10.123))
# -11
print(math.ceil(10.123))
# 11
print(math.ceil(-10.123))
# -10
print(int(10.123))
# 10
print(int(-10.123))
# -10
「無限大への丸め (rounding toward infinity; RI)」については、例えば以下のような関数で実現できる(もっといい方法があるかもしれない)。
def round_towards_infinity(x):
return int(math.copysign(math.ceil(abs(x)), x))
print(round_towards_infinity(10.123))
# 11
print(round_towards_infinity(-10.123))
# -11
abs()による絶対値をmath.ceil()で切り上げて、math.copysign()で元の値と同じ符号に戻す。math.copysign()は浮動小数点数floatを返すので、int()で整数intに変換している。