ガンマ関数と対数ガンマ(math.gamma, math.lgamma)|Python
ガンマ関数は階乗を実数・複素数に拡張した関数であり、確率論・統計学・物理学など幅広い分野で登場する。Python では math.gamma() と math.lgamma() で計算できる。
階乗とガンマ関数の関係
階乗 は非負整数に対してのみ定義される。ガンマ関数 はこれを実数全体(一部を除く)に拡張したもので、次の関係が成り立つ。
つまり、 となる。引数が 1 ずれている点に注意。
import math
# Γ(5) = 4! = 24
print(math.gamma(5)) # 24.0
# Γ(1) = 0! = 1
print(math.gamma(1)) # 1.0
# Γ(6) = 5! = 120
print(math.gamma(6)) # 120.0非整数への拡張
ガンマ関数の真価は、非整数でも計算できることにある。
import math
# Γ(1.5) ≈ 0.886(√π / 2)
print(math.gamma(1.5)) # 0.8862269254527579
# Γ(0.5) = √π ≈ 1.772
print(math.gamma(0.5)) # 1.7724538509055159
print(math.sqrt(math.pi)) # 1.7724538509055159(一致)という有名な結果がある。これはガウス積分から導かれる。
ガンマ関数の定義
ガンマ関数は積分で定義される。
この積分は で収束する。また、次の漸化式が成り立つ。
これは階乗の性質 の一般化だ。
import math
x = 3.5
print(math.gamma(x + 1)) # 11.631728396567448
print(x * math.gamma(x)) # 11.631728396567448(一致)負の値と特異点
ガンマ関数は で発散する(特異点)。
import math
# 負の非整数では計算可能
print(math.gamma(-0.5)) # -3.5449077018110318
# 0 や負の整数では ValueError
# math.gamma(0) # ValueError
# math.gamma(-1) # ValueError負の実数でも、整数でなければ計算できる。
対数ガンマ関数 lgamma
は急激に大きくなるため、大きな引数ではオーバーフローを起こす。
import math
print(math.gamma(170)) # 7.257415615307994e+306
print(math.gamma(171)) # inf(オーバーフロー)このような場合、対数ガンマ関数 を使う。math.lgamma() は を返す。
import math
# gamma(171) はオーバーフローするが lgamma なら計算可能
print(math.lgamma(171)) # 706.5730622457873
print(math.lgamma(1000)) # 5905.220423209181
# 元の値が必要なら指数を取る(オーバーフローしない範囲で)
print(math.exp(math.lgamma(10))) # 362880.0(= 9!)確率計算では対数を使うことが多いため、lgamma は非常に実用的だ。
math.gamma(x)
を直接計算。小さな引数向き。大きな値ではオーバーフローする。
math.lgamma(x)
を計算。大きな引数でもオーバーフローしない。確率計算に便利。
応用例:二項係数の計算
二項係数 はガンマ関数で表現できる。
対数を使えば、大きな数でもオーバーフローせずに計算できる。
import math
def log_binomial(n, k):
"""対数二項係数を計算"""
return math.lgamma(n + 1) - math.lgamma(k + 1) - math.lgamma(n - k + 1)
def binomial(n, k):
"""二項係数を計算(大きな値にも対応)"""
return round(math.exp(log_binomial(n, k)))
# 通常の計算
print(math.comb(100, 50)) # 100891344545564193334812497256
# lgamma を使った計算
print(binomial(100, 50)) # 100891344545564193334812497256応用例:ベータ関数との関係
ベータ関数 はガンマ関数で表現される。
import math
def beta(a, b):
"""ベータ関数を計算"""
return math.gamma(a) * math.gamma(b) / math.gamma(a + b)
print(beta(2, 3)) # 0.08333333333333333(= 1/12)
print(beta(0.5, 0.5)) # 3.141592653589793(= π)という美しい結果も確認できる。ガンマ関数は数学の様々な場所に顔を出す、重要な特殊関数である。












