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
に変換している。