Python math.exp()とは?指数関数e^xを計算する方法を解説
Pythonのmath.exp()は、自然指数関数(e の x 乗)を計算する関数です。
eはネイピア数と呼ばれる約2.718の定数で、複利計算や確率分布、機械学習のシグモイド関数など幅広い場面で使われます。
この記事では、math.exp()の使い方と注意点を解説します。
math.exp()の基本的な使い方
import math
print(math.exp(0))
print(math.exp(1))
print(math.exp(2))
print(math.exp(-1))
実行結果:
1.0
2.718281828459045
7.38905609893065
0.36787944117144233
math.exp(1)はmath.eと同じ値です。
import math
print(math.exp(1) == math.e)
実行結果:
True
math.e ** x より精度が高い
同じ計算は**演算子でもできますが、結果がわずかに異なります。
import math
for x in [10, 50, 100]:
a = math.exp(x)
b = math.e ** x
print(f"x={x:>3} exp={a:.15e} **={b:.15e} 同じ={a == b}")
実行結果(例):
x= 10 exp=2.202646579480672e+04 **=2.202646579480671e+04 同じ=False
x= 50 exp=5.184705528587072e+21 **=5.184705528587058e+21 同じ=False
x=100 exp=2.688117141816136e+43 **=2.688117141816118e+43 同じ=False
math.e ** xは、近似値であるeを繰り返し掛けるため誤差が蓄積します。
一方math.exp()は専用のアルゴリズムで直接計算するため、より正確です。指数計算にはmath.exp()を使ってください。
対数との関係
math.exp()とmath.log()は逆の関係にあります。
import math
x = 5.0
print(math.log(math.exp(x)))
print(math.exp(math.log(x)))
実行結果:
5.0
5.000000000000001
元の値に戻ります(わずかな誤差は浮動小数点数の宿命です)。
大きな値でオーバーフローする
import math
print(math.exp(700))
print(math.exp(710))
実行結果:
1.0142320547350045e+304
OverflowError: math range error
指数関数は急激に増大するため、引数が710程度を超えるとエラーになります。
興味深いことに、**演算子では無限大が返ります。
import math
print(math.e ** 710)
実行結果:
inf
同じ計算でも、エラーになるか無限大になるかが変わります。予期しない挙動を避けるため、大きな値を扱う可能性があるなら例外処理を入れましょう。
import math
def safe_exp(x):
try:
return math.exp(x)
except OverflowError:
return math.inf
print(safe_exp(1000))
逆に、極端に小さい値では0になります(アンダーフロー)。
import math
print(math.exp(-745))
print(math.exp(-746))
実行結果:
5e-324
0.0
実践例|シグモイド関数
機械学習で、値を0〜1の範囲に押し込めるために使われる関数です。
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
for x in [-5, -1, 0, 1, 5]:
print(f"x={x:>3} → {sigmoid(x):.4f}")
実行結果:
x= -5 → 0.0067
x= -1 → 0.2689
x= 0 → 0.5000
x= 1 → 0.7311
x= 5 → 0.9933
どんな入力でも0〜1に収まるため、確率として扱えます。
ただし、この実装には落とし穴があります。
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
print(sigmoid(-1000))
実行結果:
OverflowError: math range error
exp(1000)を計算しようとして失敗します。実務では、符号で処理を分けた実装が使われます。
import math
def sigmoid(x):
if x >= 0:
return 1 / (1 + math.exp(-x))
e = math.exp(x)
return e / (1 + e)
print(sigmoid(-1000))
print(sigmoid(1000))
print(sigmoid(0))
実行結果:
0.0
1.0
0.5
どちらの分岐でもexp()の引数が0以下になるため、オーバーフローしません。
実践例|連続複利の計算
import math
def continuous_compound(principal, rate, years):
return principal * math.exp(rate * years)
p = 1000000
r = 0.03
for y in [1, 5, 10, 30]:
print(f"{y:>2}年後: {continuous_compound(p, r, y):>12,.0f}円")
実行結果:
1年後: 1,030,455円
5年後: 1,161,834円
10年後: 1,349,859円
30年後: 2,459,603円
年1回の複利と比べると、わずかに大きくなります。
p, r, y = 1000000, 0.03, 30
print(f"年1回複利: {p * (1 + r) ** y:>12,.0f}円")
print(f"連続複利 : {p * math.exp(r * y):>12,.0f}円")
実践例|放射性物質の減衰
import math
def decay(initial, half_life, time):
k = math.log(2) / half_life
return initial * math.exp(-k * time)
for t in [0, 30, 60, 90]:
print(f"{t:>3}年後: {decay(100, 30, t):>6.2f}%")
実行結果:
0年後: 100.00%
30年後: 50.00%
60年後: 25.00%
90年後: 12.50%
半減期ごとに半分になっていく様子が再現できます。冷却や薬物の代謝など、「時間とともに一定割合で減る」現象はすべて同じ式で表せます。
関連する指数関数
| 関数 | 内容 |
|---|---|
math.exp(x) |
e の x 乗 |
math.expm1(x) |
exp(x) - 1を高精度に |
math.exp2(x) |
2 の x 乗(3.11以降) |
math.pow(x, y) |
x の y 乗 |
expm1()は、xが極小のときに威力を発揮します。
import math
x = 1e-16
print(math.exp(x) - 1)
print(math.expm1(x))
実行結果:
0.0
1e-16
exp(x)がほぼ1になるため、1を引くと情報がすべて失われます。金利計算など小さな値を扱う場面ではexpm1()を使います。
math.exp()まとめ
| ポイント | 内容 |
|---|---|
| 構文 | math.exp(x) |
| 意味 | e の x 乗 |
math.e ** xとの違い |
expのほうが正確 |
| 上限 | 約709(超えるとOverflowError) |
| 逆関数 | math.log() |
| 小さい値 | math.expm1()が高精度 |
シグモイド関数や減衰の計算では、オーバーフロー対策が実装の質を分けます。引数が大きくなる可能性を、必ず検討してください。






