- Python
Python mathモジュールの使い方|切り上げ・切り捨て・平方根と関数一覧
Pythonのmathモジュールとは、切り上げ・切り捨て・平方根・対数・三角関数など、数値計算でよく使う関数と定数をまとめた標準ライブラリです。 インストールは不要で、import math と1行書くだけで math.ceil(2.1) や math.sqrt(16) のように呼び出せます。
この記事では、mathの関数と定数を用途別の一覧表にまとめ、すべてに1行の実行例と結果を付けました。 さらに、ceil・floor・trunc・round・intを正の値と負の値で比べた表、sqrt・isqrt・cbrtの違い、math domain error の再現と直し方、isclose での比較、sumprod や fma が使えるバージョンまで扱います。実行結果はすべて Python 3.14.7 と Python 3.11.15 で実際に動かして確かめたものです。
mathモジュールの早見表
やりたいことから関数を探せる表です。 まずはこの表だけで用が足ります。
| やりたいこと | 書き方 | 結果 | 補足 |
|---|---|---|---|
| 切り上げ | math.ceil(2.1) |
3 |
戻り値は int |
| 切り捨て(小さい方へ) | math.floor(2.9) |
2 |
負の値では -2.9 → -3 |
| 小数部を取り除く(0の方へ) | math.trunc(-2.9) |
-2 |
int(-2.9) と同じ結果 |
| 平方根 | math.sqrt(16) |
4.0 |
戻り値は float |
| 整数の平方根 | math.isqrt(17) |
4 |
戻り値は int(3.8以降) |
| 立方根 | math.cbrt(-8) |
-2.0 |
負の値も可(3.11以降) |
| 累乗 | math.pow(2, 10) |
1024.0 |
整数のままなら 2 ** 10 |
| 円周率 | math.pi |
3.141592653589793 |
定数 |
| 自然対数・常用対数 | math.log(math.e) / math.log10(1000) |
1.0 / 3.0 |
2が底なら math.log2 |
| 度とラジアンの変換 | math.radians(180) / math.degrees(math.pi) |
3.141592653589793 / 180.0 |
三角関数はラジアンで渡す |
| 最大公約数・最小公倍数 | math.gcd(12, 18) / math.lcm(4, 6) |
6 / 12 |
lcm は 3.9以降 |
| 階乗・組み合わせ | math.factorial(5) / math.comb(5, 2) |
120 / 10 |
comb は 3.8以降 |
| 小数どうしの比較 | math.isclose(0.1 + 0.2, 0.3) |
True |
== では False |
| NaN の判定 | math.isnan(math.nan) |
True |
nan == nan は False |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python mathモジュールの使い方|切り上げ・切り捨て・平方根と関数一覧」
mathモジュールの基本と読み込み方
import の書き方3通り
基本は import math です。 関数名の前に math. が付くので、どのモジュールの関数かがひと目でわかります。
import math
print(math.sqrt(16)) # 4.0
from math import sqrt, pi # 使う名前だけ取り込む
print(sqrt(16), pi) # 4.0 3.141592653589793
import math as m # 別名を付ける
print(m.floor(2.9)) # 2
| 書き方 | 呼び出し方 | 向いている場面 |
|---|---|---|
import math |
math.sqrt(x) |
ふだんの基本形。出どころが明確 |
from math import sqrt |
sqrt(x) |
同じ関数を何度も書く数式 |
import math as m |
m.sqrt(x) |
数式が長くなるとき |
from math import * |
sqrt(x) |
対話モードでの試し書き向き。pow など組み込み関数と同じ名前が上書きされるため、ファイルに残すコードでは上の3つを使うと読みやすくなります |
関数と定数はいくつあるか
dir(math) で数えると、Python 3.14.7 では62個(関数57+定数5)、Python 3.11.15 では60個でした。差の2個は、3.12で追加された sumprod と、3.13で追加された fma です。
import math
names = [n for n in dir(math) if not n.startswith("_")]
print(len(names)) # 3.14.7 では 62、3.11.15 では 60
mathが扱うのは実数(int と float)です。複素数は cmath、配列全体への一括計算は NumPy、10進数での厳密な計算は decimal という役割分担になっています。
切り上げ・切り捨て:ceil・floor・trunc・round・intの違い
正負の値で比べた表
切り上げは math.ceil、切り捨ては math.floor、小数部を取り除くのは math.trunc です。 正の値では floor と trunc が同じ結果になりますが、負の値で差が出ます。次の表は Python 3.14.7 で実行した結果です(3.11.15 でも同じでした)。
| 値 x | math.ceil(x) |
math.floor(x) |
math.trunc(x) |
int(x) |
round(x) |
|---|---|---|---|---|---|
2.4 |
3 | 2 | 2 | 2 | 2 |
2.5 |
3 | 2 | 2 | 2 | 2 |
2.6 |
3 | 2 | 2 | 2 | 3 |
3.5 |
4 | 3 | 3 | 3 | 4 |
0.5 |
1 | 0 | 0 | 0 | 0 |
-0.5 |
0 | -1 | 0 | 0 | 0 |
-2.4 |
-2 | -3 | -2 | -2 | -2 |
-2.5 |
-2 | -3 | -2 | -2 | -2 |
-2.6 |
-2 | -3 | -2 | -2 | -3 |
-3.5 |
-3 | -4 | -3 | -3 | -4 |
表から読み取れるポイントは次の4つです。
- ceil は「数直線で右(大きい方)」へ進みます。
-2.4の切り上げは-2です。 - floor は「数直線で左(小さい方)」へ進みます。
-2.4の切り捨ては-3になります。 - trunc と int は「0に近い方」へ進みます。 正の値では floor と同じ、負の値では ceil と同じ結果です。
- round は「ちょうど真ん中(.5)のとき偶数側」へ丸めます。
round(2.5)は 2、round(3.5)は 4 です。学校で習う四捨五入とは結果が変わる値があります。
どれを選ぶかの判断表
| やりたいこと | 選ぶもの | 例と結果 |
|---|---|---|
| 必要な箱の数・ページ数(余りが出たら1つ増やす) | math.ceil |
math.ceil(95 / 10) → 10 |
| 負の値でも常に小さい方へそろえる | math.floor |
math.floor(-2.4) → -3 |
| 符号に関係なく小数部を取り除く | math.trunc または int |
math.trunc(-2.9) → -2 |
| 近い整数にする(.5は偶数側) | round |
round(2.5) → 2 |
| 学校で習う四捨五入(.5は必ず繰り上げ) | decimal の ROUND_HALF_UP |
下のコードを参照 |
math.trunc(x) と int(x) は数値に対しては同じ結果です。違いは文字列で、int("3") は 3 を返しますが、math.trunc("3") は TypeError: type str doesn't define __trunc__ method になります。「数値の小数部を取り除く」という意図をコードで伝えたいときは trunc、文字列からの変換も兼ねるときは int と使い分けると読みやすくなります。
小数第n位・10や100の単位で切り上げ/切り捨てる
ceil と floor は整数に丸める関数なので、桁を指定したいときは「掛けて、丸めて、割る」の形にします。
import math
x = 3.14159
print(math.ceil(x * 100) / 100) # 3.15 小数第3位を切り上げ
print(math.floor(x * 100) / 100) # 3.14 小数第3位を切り捨て
print(math.floor(-3.14159 * 100) / 100) # -3.15 floor は小さい方へ
print(math.trunc(-3.14159 * 100) / 100) # -3.14 trunc は0の方へ
print(math.ceil(1234 / 100) * 100) # 1300 100単位で切り上げ
print(math.floor(1234 / 100) * 100) # 1200 100単位で切り捨て
整数どうしなら、mathを使わずに //(切り捨て除算)でも書けます。1234 // 100 は 12、-(-1234 // 100) は 13 です。-(-a // b) は「符号を反転して切り捨て、もう一度反転する」ことで切り上げになる定番の書き方です。
つまずく箇所:小数の掛け算のあとに ceil を使うと1つ多くなることがある
float の計算結果にはごく小さな誤差が乗るため、ceil の結果が1つ大きくなる値があります。
import math
print(0.1 * 3) # 0.30000000000000004
print(math.ceil(0.1 * 3 * 10)) # 4 (3 を期待していた)
print(math.ceil(round(0.1 * 3 * 10, 9))) # 3 先に誤差を落としてから切り上げ
0.1 * 3 が内部では 0.30000000000000004 になるため、10倍すると3をわずかに超え、ceil が4を返します。対処は2つあります。
| 対処 | 書き方 | 向いている場面 |
|---|---|---|
先に round で誤差を落とす |
math.ceil(round(v, 9)) |
手軽に直したいとき |
| 10進数で計算する | decimal.Decimal("0.1") * 3 |
小数の桁を厳密に扱いたいとき |
.5 を必ず繰り上げる四捨五入は decimal で書けます。
from decimal import Decimal, ROUND_HALF_UP
print(Decimal("2.5").quantize(Decimal("1"), rounding=ROUND_HALF_UP)) # 3
print(Decimal("2.675").quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)) # 2.68
print(round(2.675, 2)) # 2.67
round(2.675, 2) が 2.67 になるのは、float の 2.675 が内部では 2.67499999999999982236431605997495353221893310546875 として保持されているためです(Decimal(2.675) で確認できます)。
丸め・小数部の関数一覧
| 関数 | 実行例 | 結果 | 説明 |
|---|---|---|---|
math.ceil(x) |
math.ceil(2.1) |
3 |
x 以上で最小の整数 |
math.floor(x) |
math.floor(2.9) |
2 |
x 以下で最大の整数 |
math.trunc(x) |
math.trunc(-2.9) |
-2 |
小数部を取り除く |
math.fabs(x) |
math.fabs(-3) |
3.0 |
絶対値を float で返す(abs(-3) は 3) |
math.modf(x) |
math.modf(3.75) |
(0.75, 3.0) |
小数部と整数部に分ける |
math.fmod(x, y) |
math.fmod(-7, 3) |
-1.0 |
余り。符号は x に合わせる(-7 % 3 は 2) |
math.remainder(x, y) |
math.remainder(7, 4) |
-1.0 |
最も近い倍数との差(3.7以降) |
math.copysign(x, y) |
math.copysign(3, -0.0) |
-3.0 |
x の大きさに y の符号を付ける |
math.ceil(2.1) の戻り値の型は int です。math.ceil(math.inf) は OverflowError: cannot convert float infinity to integer、math.ceil(math.nan) は ValueError: cannot convert float NaN to integer になるので、外から来た値を丸める前には後述の math.isfinite で確かめると安心です。
平方根と累乗:sqrt・isqrt・cbrtの違い
3つの関数の比較表
平方根は math.sqrt、整数のまま平方根を求めるなら math.isqrt、立方根は math.cbrt です。
| 関数 | 実行例 | 結果 | 戻り値の型 | 負の値を渡すと | 追加バージョン |
|---|---|---|---|---|---|
math.sqrt(x) |
math.sqrt(16) |
4.0 |
float | ValueError | 当初から |
math.sqrt(x) |
math.sqrt(2) |
1.4142135623730951 |
float | ― | ― |
math.isqrt(n) |
math.isqrt(17) |
4 |
int | ValueError | 3.8 |
math.cbrt(x) |
math.cbrt(-8) |
-2.0 |
float | 計算できる | 3.11 |
math.cbrt(x) |
math.cbrt(27) |
3.0000000000000004 |
float | ― | ― |
x ** 0.5 |
16 ** 0.5 |
4.0 |
float | 複素数になる | 演算子 |
math.isqrt(n) は「2乗して n を超えない最大の整数」を返します。math.isqrt(17) が 4 なのは、4×4=16 ≤ 17 < 25=5×5 だからです。float を渡すと TypeError: 'float' object cannot be interpreted as an integer になります。
大きな整数では isqrt が正確
float は約15〜17桁までしか正確に表せないため、大きな整数の平方根は int(math.sqrt(n)) だとずれることがあります。
import math
n = 99999999999999999 ** 2 # 17桁の数の2乗
print(int(math.sqrt(n))) # 100000000000000000 (1だけずれる)
print(math.isqrt(n)) # 99999999999999999 (正確)
print(math.isqrt(10 ** 400) == 10 ** 200) # True
print(math.sqrt(10 ** 400))
100000000000000000
99999999999999999
True
OverflowError: int too large to convert to float
math.sqrt は引数をいったん float に変換するので、float の範囲を超える整数は OverflowError になります。math.isqrt は整数のまま計算するため、桁数に上限がありません。素数判定や「平方数かどうか」の判定には isqrt が向いています。
import math
def is_prime(n: int) -> bool:
if n < 2:
return False
return all(n % i for i in range(2, math.isqrt(n) + 1))
print([n for n in range(30) if is_prime(n)])
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
立方根は cbrt、ただし結果は isclose で比べる
math.cbrt(27) の結果は 3.0000000000000004 で、math.cbrt(27) == 3 は False でした(3.14.7・3.11.15とも)。立方根の結果を整数と比べるときは math.isclose(math.cbrt(27), 3)(結果は True)か、round(math.cbrt(27)) を使います。
負の値の立方根は、書き方によって結果が大きく変わります。
| 書き方 | 結果 |
|---|---|
math.cbrt(-8) |
-2.0 |
(-8) ** (1/3) |
(1.0000000000000002+1.7320508075688772j)(複素数) |
math.pow(-8, 1/3) |
ValueError: math domain error |
実数の答え -2.0 がほしいときは math.cbrt を選びます。
平方根・累乗・指数の関数一覧
| 関数 | 実行例 | 結果 | 説明 |
|---|---|---|---|
math.sqrt(x) |
math.sqrt(16) |
4.0 |
平方根 |
math.isqrt(n) |
math.isqrt(17) |
4 |
整数の平方根(3.8以降) |
math.cbrt(x) |
math.cbrt(-8) |
-2.0 |
立方根(3.11以降) |
math.pow(x, y) |
math.pow(2, 10) |
1024.0 |
累乗。常に float |
math.exp(x) |
math.exp(1) |
2.718281828459045 |
e の x 乗 |
math.exp2(x) |
math.exp2(10) |
1024.0 |
2 の x 乗(3.11以降) |
math.expm1(x) |
math.expm1(1e-10) |
1.00000000005e-10 |
e の x 乗 − 1 を、x が小さくても精度よく |
math.hypot(*座標) |
math.hypot(3, 4) |
5.0 |
原点からの距離。math.hypot(1, 2, 2) は 3.0 |
math.dist(p, q) |
math.dist((0, 0), (3, 4)) |
5.0 |
2点間の距離(3.8以降) |
math.pow(2, 10) は 1024.0(float)、2 ** 10 は 1024(int)です。整数のまま結果がほしいときは ** 演算子、float でそろえたいときは math.pow と覚えると迷いません。
対数と指数:log・log2・log10
math.log(x) は自然対数(底が e)、math.log(x, 底) で底を指定できます。 底が2や10のときは専用の関数のほうが正確です。
| 関数 | 実行例 | 結果 | 説明 |
|---|---|---|---|
math.log(x) |
math.log(math.e) |
1.0 |
自然対数 |
math.log(x, base) |
math.log(8, 2) |
3.0 |
底を指定 |
math.log2(x) |
math.log2(1024) |
10.0 |
底が2(3.3以降) |
math.log10(x) |
math.log10(1000) |
3.0 |
底が10 |
math.log1p(x) |
math.log1p(1e-10) |
9.999999999500001e-11 |
log(1+x) を、x が小さくても精度よく |
底を指定する形は内部で割り算をするため、わずかな誤差が出る値があります。
import math
print(math.log(1000, 10)) # 2.9999999999999996
print(math.log10(1000)) # 3.0
print(math.log(125, 5)) # 3.0000000000000004
底が10なら math.log10、底が2なら math.log2 を使うと、きりのよい値がそのまま返ります。 それ以外の底では、結果を math.isclose で比べるか round で整えます。整数の桁数は math.floor(math.log10(12345)) + 1(結果は 5)でも求められますが、len(str(12345)) のほうが誤差の心配がなく簡単です。
三角関数と角度の変換
mathの三角関数は、角度を「度」ではなく「ラジアン」で受け取ります。 度で考えているときは math.radians で変換してから渡します。
import math
print(math.sin(30)) # -0.9880316240928618 30ラジアンとして計算される
print(math.sin(math.radians(30))) # 0.49999999999999994 30度
print(round(math.sin(math.radians(30)), 10)) # 0.5
| 関数 | 実行例 | 結果 | 説明 |
|---|---|---|---|
math.radians(度) |
math.radians(180) |
3.141592653589793 |
度 → ラジアン |
math.degrees(rad) |
math.degrees(math.pi) |
180.0 |
ラジアン → 度 |
math.sin(x) |
math.sin(math.pi / 2) |
1.0 |
正弦 |
math.cos(x) |
math.cos(math.pi) |
-1.0 |
余弦 |
math.tan(x) |
math.tan(math.pi / 4) |
0.9999999999999999 |
正接 |
math.asin(x) |
math.asin(1) |
1.5707963267948966 |
逆正弦(引数は -1〜1) |
math.acos(x) |
math.acos(1) |
0.0 |
逆余弦(引数は -1〜1) |
math.atan(x) |
math.atan(1) |
0.7853981633974483 |
逆正接 |
math.atan2(y, x) |
math.atan2(1, -1) |
2.356194490192345 |
座標から角度。象限を正しく判定 |
math.sinh(x) |
math.sinh(1) |
1.1752011936438014 |
双曲線正弦 |
math.cosh(x) |
math.cosh(0) |
1.0 |
双曲線余弦 |
math.tanh(x) |
math.tanh(1) |
0.7615941559557649 |
双曲線正接 |
このほか逆双曲線関数の asinh・acosh・atanh があります。
math.sin(math.pi) は 0 ではなく 1.2246467991473532e-16 を返します。 math.pi が円周率の近似値(float)だからです。0かどうかは math.isclose(math.sin(math.pi), 0, abs_tol=1e-9)(結果は True)で判定します。
2点を結ぶ線の角度は atan2 で求めます。引数の順番が (y, x) である点に注意してください。
import math
p, q = (1, 2), (4, 6)
print(math.dist(p, q)) # 5.0
print(math.degrees(math.atan2(q[1] - p[1], q[0] - p[0]))) # 53.13010235415598
整数演算:階乗・最大公約数・組み合わせ
整数を受け取り整数を返す関数は、桁数がどれだけ大きくても正確に計算できます。
| 関数 | 実行例 | 結果 | 説明 |
|---|---|---|---|
math.factorial(n) |
math.factorial(5) |
120 |
階乗 |
math.gcd(*整数) |
math.gcd(12, 18, 30) |
6 |
最大公約数。3個以上は 3.9以降 |
math.lcm(*整数) |
math.lcm(4, 6) |
12 |
最小公倍数(3.9以降) |
math.comb(n, k) |
math.comb(5, 2) |
10 |
組み合わせ nCk(3.8以降) |
math.perm(n, k) |
math.perm(5, 2) |
20 |
順列 nPk(3.8以降) |
math.isqrt(n) |
math.isqrt(17) |
4 |
整数の平方根(3.8以降) |
math.prod(iterable) |
math.prod([1, 2, 3, 4]) |
24 |
すべての積(3.8以降)。空なら 1 |
math.factorial(2.0) のように float を渡すと TypeError: 'float' object cannot be interpreted as an integer になります。math.factorial(-1) は ValueError: factorial() not defined for negative values です。「10人から3人を選ぶ」通り数は math.comb(10, 3) で 120 と求められます。
合計と積:fsum・prod・sumprod・fma
| 関数 | 実行例 | 結果 | 追加バージョン |
|---|---|---|---|
math.fsum(iterable) |
math.fsum([0.1] * 10) |
1.0 |
当初から |
math.prod(iterable) |
math.prod([1, 2, 3, 4]) |
24 |
3.8 |
math.sumprod(p, q) |
math.sumprod([1, 2, 3], [4, 5, 6]) |
32 |
3.12 |
math.fma(x, y, z) |
math.fma(2, 3, 4) |
10.0 |
3.13 |
fsum:小数の合計を誤差なく求める
math.fsum は途中の誤差を追跡しながら合計するので、float の合計が正確になります。組み込みの sum との差は、Pythonのバージョンによって変わりました。
| 式 | Python 3.11.15 | Python 3.14.7 |
|---|---|---|
sum([0.1] * 10) |
0.9999999999999999 |
1.0 |
math.fsum([0.1] * 10) |
1.0 |
1.0 |
sum([0.1, 0.2, 0.3]) |
0.6000000000000001 |
0.6 |
sum([1e16, 1.0, -1e16]) |
0.0 |
1.0 |
math.fsum([1e16, 1.0, -1e16]) |
1.0 |
1.0 |
手元の実行では、3.14.7 の sum は float の合計で fsum と同じ結果を返しました。どのバージョンでも同じ結果にしたいときは math.fsum を選ぶと確実です。
sumprod(3.12以降):2つのリストの積の合計
math.sumprod(p, q) は、対応する要素どうしを掛けて合計します。単価と数量から合計を出す、ベクトルの内積を求める、といった場面で1行になります。
import math
prices = [120, 80, 300]
counts = [2, 5, 1]
print(math.sumprod(prices, counts)) # 940
print(sum(p * c for p, c in zip(prices, counts))) # 940 3.11以前はこちら
Python 3.11.15 で math.sumprod を呼ぶと AttributeError: module 'math' has no attribute 'sumprod' になりました。3.11以前でも動かすコードでは sum(... for ... in zip(...)) の形を使います。
fma(3.13以降):掛けて足す計算を1回の丸めで行う
math.fma(x, y, z) は x * y + z を、途中で丸めずに計算します。ふつうの式は「掛け算で1回、足し算で1回」丸めが入りますが、fma は最後の1回だけです。
import math
print(math.fma(2, 3, 4)) # 10.0
print(0.1 * 10 - 1) # 0.0
print(math.fma(0.1, 10, -1)) # 5.551115123125783e-17
0.1 は内部では0.1よりわずかに大きい値です。ふつうの式では 0.1 * 10 が丸められて 1.0 になり差が消えますが、fma はその差 5.55e-17 を取り出せます。数値計算の精度を詰めたいときに使う関数で、ふだんの計算では x * y + z のままで十分です。
判定と比較:isclose・isnan・isinf・isfinite
小数どうしは == ではなく isclose で比べる
float の計算結果を == で比べると、見た目が同じでも False になることがあります。math.isclose を使うと「十分に近いか」で判定できます。
import math
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
print(math.isclose(0.1 + 0.2, 0.3)) # True
math.isclose(a, b, rel_tol=1e-09, abs_tol=0.0) には許容範囲の指定が2つあります。
| 引数 | 意味 | 既定値 | 使いどころ |
|---|---|---|---|
rel_tol |
相対的な許容差(大きいほうの値に対する割合) | 1e-09 |
ふつうの値どうしの比較 |
abs_tol |
絶対的な許容差 | 0.0 |
0との比較で指定する |
0と比べるときは abs_tol の指定が必要です。 相対的な許容差は「値の大きさ×割合」なので、相手が0だと許容範囲も0になるためです。
import math
print(math.isclose(1e-10, 0)) # False
print(math.isclose(1e-10, 0, abs_tol=1e-9)) # True
print(math.isclose(1000.0, 1000.1, rel_tol=1e-3)) # True 0.1%以内なら同じとみなす
NaN と無限大の判定
| 関数・定数 | 実行例 | 結果 | 説明 |
|---|---|---|---|
math.isclose(a, b) |
math.isclose(0.1 + 0.2, 0.3) |
True |
近いかどうか(3.5以降) |
math.isnan(x) |
math.isnan(math.nan) |
True |
NaN(数でない値)か |
math.isinf(x) |
math.isinf(-math.inf) |
True |
正または負の無限大か |
math.isfinite(x) |
math.isfinite(math.inf) |
False |
有限の数か(NaN と無限大以外) |
math.nextafter(x, y) |
math.nextafter(1.0, 2.0) |
1.0000000000000002 |
y 方向の次の float(3.9以降) |
math.ulp(x) |
math.ulp(1.0) |
2.220446049250313e-16 |
x の最下位ビットの大きさ(3.9以降) |
math.frexp(x) |
math.frexp(8.0) |
(0.5, 4) |
仮数と指数に分ける(0.5 × 2の4乗) |
math.ldexp(x, i) |
math.ldexp(0.5, 4) |
8.0 |
frexp の逆 |
NaN は自分自身と比べても等しくなりません。 math.nan == math.nan は False なので、NaN かどうかは必ず math.isnan で判定します。CSVなどから読み込んだ値を計算に使う前に math.isfinite(x) を通すと、NaN と無限大をまとめて見分けられます。
定数と特殊関数
| 名前 | 値・実行例 | 説明 |
|---|---|---|
math.pi |
3.141592653589793 |
円周率 π |
math.e |
2.718281828459045 |
自然対数の底 |
math.tau |
6.283185307179586 |
2π(3.6以降)。円周は math.tau * r |
math.inf |
inf |
正の無限大(3.5以降)。math.inf > 10 ** 400 は True |
math.nan |
nan |
数でない値(3.5以降) |
math.erf(x) |
math.erf(1) → 0.8427007929497149 |
誤差関数。erfc は 1 − erf |
math.gamma(x) |
math.gamma(5) → 24.0 |
ガンマ関数(4の階乗と同じ値) |
math.lgamma(x) |
math.lgamma(5) → 3.178053830347945 |
ガンマ関数の絶対値の自然対数 |
math.inf は「最小値を探すときの初期値」として便利です。best = math.inf としておけば、どんな数と比べても最初の1回で置き換わります。
import math
r = 3
print(round(math.pi * r ** 2, 2)) # 28.27 円の面積
print(round(math.tau * r, 2)) # 18.85 円周
math domain errorの原因と直し方
エラーを再現する
ValueError: math domain error は、関数が計算できる範囲(定義域)の外の値を渡したときに出るエラーです。 負の値の平方根、0や負の値の対数、-1〜1の外の値の逆三角関数が代表例です。
Python 3.11.15 では次のように表示されました。
>>> math.sqrt(-1)
ValueError: math domain error
>>> math.log(0)
ValueError: math domain error
>>> math.acos(2)
ValueError: math domain error
Python 3.14.7 では、同じ操作でも原因がわかるメッセージに変わっていました。 検索したエラー文と手元の表示が違うときは、Pythonのバージョンを確かめてみてください。
| 式 | Python 3.11.15 | Python 3.14.7 |
|---|---|---|
math.sqrt(-1) |
ValueError: math domain error |
ValueError: expected a nonnegative input, got -1.0 |
math.log(0) |
ValueError: math domain error |
ValueError: expected a positive input |
math.log(-1) |
ValueError: math domain error |
ValueError: expected a positive input |
math.acos(2) |
ValueError: math domain error |
ValueError: expected a number in range from -1 up to 1, got 2.0 |
math.gamma(0) |
ValueError: math domain error |
ValueError: expected a noninteger or positive integer, got 0.0 |
math.pow(-8, 1/3) |
ValueError: math domain error |
ValueError: math domain error |
math.pow(0, -1) |
ValueError: math domain error |
ValueError: math domain error |
math.exp(1000) |
OverflowError: math range error |
OverflowError: math range error |
math range error は別のエラーで、結果が float で表せる範囲を超えたときに出ます。
原因別の直し方
| 原因 | 直す前 | 直した後 |
|---|---|---|
| 負の値の平方根 | math.sqrt(x) |
先に if x < 0: で分ける。複素数でよければ cmath.sqrt(x) |
| 0や負の値の対数 | math.log(x) |
if x > 0: で分ける。0に近い値を足すなら math.log1p(x) |
| 誤差で 1 をわずかに超えた値の acos / asin | math.acos(c) |
math.acos(max(-1.0, min(1.0, c))) |
| 負の値の立方根 | math.pow(x, 1/3) |
math.cbrt(x) |
| 0 の負の累乗 | math.pow(0, -1) |
0 かどうかを先に判定する |
見つけにくい例:計算誤差で1をわずかに超える
理論上は -1〜1 に収まる値でも、float の誤差で 1.0000000000000002 になり、acos がエラーになることがあります。 同じベクトルどうしの角度を求める例で再現します。
import math
a = (1, 1, 1)
dot = sum(x * x for x in a) # 同じベクトル同士の内積
cos = dot / (math.hypot(*a) * math.hypot(*a)) # 理論上は 1.0
print(repr(cos))
try:
print(math.acos(cos))
except ValueError as e:
print("ValueError:", e)
cos = max(-1.0, min(1.0, cos)) # -1〜1 に収める
print(math.acos(cos))
1.0000000000000002
ValueError: expected a number in range from -1 up to 1, got 1.0000000000000002
0.0
(Python 3.14.7 の結果。3.11.15 では2行目が ValueError: math domain error でした。)max(-1.0, min(1.0, 値)) で範囲に収めてから渡すのが定番の対処です。
入力値を事前に確かめる書き方と、例外を受け取る書き方のどちらでも対応できます。
import math
import cmath
def safe_sqrt(x):
if x < 0:
return None
return math.sqrt(x)
print(safe_sqrt(9), safe_sqrt(-9)) # 3.0 None
print(cmath.sqrt(-1)) # 1j
コピペで使える用途別コード
よくある8つの計算を1つのファイルにまとめました。 そのまま保存して python3 sample.py で動きます(Python 3.8以降)。
import math
# 1) ページ数:95件を10件ずつ表示
print(math.ceil(95 / 10)) # 10
# 2) 2点間の距離と角度
p, q = (1, 2), (4, 6)
print(math.dist(p, q)) # 5.0
print(math.degrees(math.atan2(q[1] - p[1], q[0] - p[0])))
# 3) 円の面積と円周(半径3)
r = 3
print(round(math.pi * r ** 2, 2), round(math.tau * r, 2))
# 4) 素数判定(isqrt で調べる範囲を絞る)
def is_prime(n: int) -> bool:
if n < 2:
return False
return all(n % i for i in range(2, math.isqrt(n) + 1))
print([n for n in range(30) if is_prime(n)])
# 5) 整数の桁数
print(len(str(12345)), math.floor(math.log10(12345)) + 1)
# 6) 組み合わせ:10人から3人を選ぶ
print(math.comb(10, 3))
# 7) 小数第2位までで切り上げ・切り捨て
x = 3.14159
print(math.ceil(x * 100) / 100, math.floor(x * 100) / 100)
# 8) 100単位で切り上げ・切り捨て
print(math.ceil(1234 / 100) * 100, math.floor(1234 / 100) * 100)
10
5.0
53.13010235415598
28.27 18.85
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
5 5
120
3.15 3.14
1300 1200
Python 3.14.7 と 3.11.15 で同じ出力になることを確かめました。
バージョン別:追加された関数の一覧
新しめの関数は、動かすPythonのバージョンによっては使えません。 追加バージョンは公式ドキュメント(Python 3.14.8 の math ページ)で確認し、3.11.15 と 3.14.7 で動作を確かめました。
| バージョン | 追加された関数・定数 |
|---|---|
| 3.5 | isclose、gcd、inf、nan |
| 3.6 | tau |
| 3.7 | remainder |
| 3.8 | isqrt、comb、perm、prod、dist(hypot が3個以上の引数に対応) |
| 3.9 | lcm、nextafter、ulp(gcd が任意個数の引数に対応) |
| 3.11 | cbrt、exp2 |
| 3.12 | sumprod(nextafter に steps 引数) |
| 3.13 | fma |
バージョンは python3 --version、関数があるかどうかは hasattr(math, "sumprod") で確かめられます。
mathと他の手段の使い分け
| 計算の対象 | 選ぶもの | 理由 |
|---|---|---|
| 1つの数値(int・float) | math |
標準ライブラリで追加の準備が不要 |
| リストや配列の全要素 | NumPy(np.sqrt(arr) など) |
配列をまとめて計算できる |
| 複素数 | cmath |
cmath.sqrt(-1) が 1j を返す |
| 小数の桁を厳密に扱う | decimal |
10進数のまま計算し、丸め方を指定できる |
| 分数のまま扱う | fractions |
Fraction(1, 3) のように誤差なく保持 |
| 平均・中央値などの統計 | statistics |
mean、median などがそろう |
mathの関数にリストをそのまま渡すと TypeError: must be real number, not list になります。リストの各要素に適用するときは [math.sqrt(v) for v in values] のように内包表記を使います。
よくある質問
Q. math.floor と int はどう違いますか?
A. 正の値では同じ結果ですが、負の値で変わります。math.floor(-2.5) は -3(小さい方へ)、int(-2.5) は -2(0の方へ)です。int と同じ動きをするのは math.trunc です。
Q. round(2.5) が 3 ではなく 2 になるのはなぜですか?
A. Pythonの round は、ちょうど真ん中の値を偶数側へ丸める方式だからです。round(3.5) は 4 になります。.5 を必ず繰り上げたいときは、decimal の ROUND_HALF_UP を使います。
Q. math.sqrt と ** 0.5 はどちらを使えばよいですか?
A. 実数の平方根なら math.sqrt が読みやすく、負の値を渡したときにエラーで気づけます。(-4) ** 0.5 は複素数を返すため、意図しない値がそのまま後続の計算へ流れることがあります。大きな整数なら math.isqrt が正確です。
Q. math.sumprod や math.fma が見つからないと表示されます。
A. AttributeError: module 'math' has no attribute 'sumprod' は、Pythonが 3.11 以前のときに出ます。sumprod は 3.12、fma は 3.13 で追加されました。sum(x * y for x, y in zip(p, q)) で同じ計算ができます。
まとめ
- 切り上げは
math.ceil、切り捨てはmath.floor、小数部の除去はmath.trunc。 負の値では floor が小さい方へ、trunc と int が0の方へ進む。 roundは .5 を偶数側へ丸める。 必ず繰り上げたいときはdecimalのROUND_HALF_UP。- 平方根は
math.sqrt(float)、大きな整数はmath.isqrt(int)、立方根はmath.cbrt。 負の値の立方根も cbrt なら実数で返る。 - 小数の比較は
math.isclose。 0と比べるときはabs_tolを指定する。NaN の判定はmath.isnan。 math domain errorは定義域の外の値が原因。 事前の条件分岐か、max(-1.0, min(1.0, x))で範囲に収めて直す。3.14 では原因がわかるメッセージに変わっている。sumprodは 3.12、fmaは 3.13、cbrtとexp2は 3.11 で追加。 動かす環境のバージョンを確かめてから使う。- 三角関数はラジアンで渡す。 度で考えるときは
math.radiansで変換する。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python mathモジュールの使い方|切り上げ・切り捨て・平方根と関数一覧」
株式会社RJCでは、Pythonのmathモジュールや数値計算の基礎を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。