いろは2986023 views
高校国語785655 views
高校倫理1433119 views
高校化学2913383 views
教育148875 views
英語607877 views
中学理科1626207 views
雑学1472593 views
りんご192546 views
中学数学621382 views
Help
Tools

English

ガンマ関数と対数ガンマ(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(= π)

という美しい結果も確認できる。ガンマ関数は数学の様々な場所に顔を出す、重要な特殊関数である。