Pythonで指数関数・対数関数を完全マスター【exp・log・log10・log2】

 

Pythonのmathモジュールを使えば、指数関数や対数関数の計算を簡単かつ高精度で行うことができます。この記事では、自然指数関数、常用対数、2進対数まで、実践的なサンプルコードと共に詳しく解説します。

指数関数・対数関数の基本

自然指数関数 exp()

import math

# 自然指数関数 e^x
x_values = [0, 1, 2, -1, 0.5]

print("x     | e^x")
print("-" * 15)

for x in x_values:
    exp_val = math.exp(x)
    print(f"{x:4.1f} | {exp_val:8.3f}")

# ネイピア数の確認
e = math.exp(1)
print(f"\nネイピア数 e = {e}")
print(f"math.e = {math.e}")

自然対数 log()

import math

# 自然対数 ln(x)
x_values = [1, math.e, 10, 100, 0.5]

print("x      | ln(x)")
print("-" * 17)

for x in x_values:
    if x > 0:
        log_val = math.log(x)
        print(f"{x:6.2f} | {log_val:8.3f}")
    else:
        print(f"{x:6.2f} | 定義域外")

# 指数と対数の逆関数性の確認
x = 5
print(f"\nln(e^{x}) = {math.log(math.exp(x))}")
print(f"e^(ln({x})) = {math.exp(math.log(x))}")

常用対数 log10()

import math

# 常用対数 log₁₀(x)
powers_of_10 = [1, 10, 100, 1000, 0.1, 0.01]

print("x       | log₁₀(x)")
print("-" * 20)

for x in powers_of_10:
    log10_val = math.log10(x)
    print(f"{x:7.2f} | {log10_val:8.1f}")

# 桁数の計算
number = 12345
digits = int(math.log10(number)) + 1
print(f"\n{number}の桁数: {digits}")

2進対数 log2()

import math

# 2進対数 log₂(x)
powers_of_2 = [1, 2, 4, 8, 16, 32, 64, 128]

print("x    | log₂(x)")
print("-" * 15)

for x in powers_of_2:
    log2_val = math.log2(x)
    print(f"{x:3} | {log2_val:7.1f}")

# ビット数の計算
number = 255
bits_needed = int(math.log2(number)) + 1
print(f"\n{number}を表現するのに必要なビット数: {bits_needed}")

任意の底の対数

log(x, base)の使用

import math

def logarithm_different_bases(x):
    print(f"x = {x}の各底での対数:")
    print("-" * 30)
    
    bases = [2, 3, 5, 10, math.e]
    base_names = ["2", "3", "5", "10", "e"]
    
    for base, name in zip(bases, base_names):
        if base == math.e:
            log_val = math.log(x)
        else:
            log_val = math.log(x, base)
        print(f"log_{name}({x}) = {log_val:.3f}")

logarithm_different_bases(100)

底の変換公式

import math

def log_base_conversion(x, base):
    # log_base(x) = ln(x) / ln(base)
    return math.log(x) / math.log(base)

# 例:log₃(27) = 3
x, base = 27, 3
result1 = math.log(x, base)              # 直接計算
result2 = log_base_conversion(x, base)   # 変換公式

print(f"log_{base}({x}) = {result1:.6f}")
print(f"変換公式 = {result2:.6f}")
print(f"誤差: {abs(result1 - result2):.2e}")

指数・対数の性質と法則

指数法則の確認

import math

def verify_exponential_laws():
    a, b = 2, 3
    
    # e^(a+b) = e^a * e^b
    left = math.exp(a + b)
    right = math.exp(a) * math.exp(b)
    print(f"e^({a}+{b}) = {left:.6f}")
    print(f"e^{a} * e^{b} = {right:.6f}")
    print(f"誤差: {abs(left - right):.2e}\n")
    
    # e^(a-b) = e^a / e^b
    left = math.exp(a - b)
    right = math.exp(a) / math.exp(b)
    print(f"e^({a}-{b}) = {left:.6f}")
    print(f"e^{a} / e^{b} = {right:.6f}")
    print(f"誤差: {abs(left - right):.2e}\n")
    
    # (e^a)^b = e^(a*b)
    left = math.exp(a) ** b
    right = math.exp(a * b)
    print(f"(e^{a})^{b} = {left:.6f}")
    print(f"e^({a}*{b}) = {right:.6f}")
    print(f"誤差: {abs(left - right):.2e}")

verify_exponential_laws()

対数法則の確認

import math

def verify_logarithm_laws():
    a, b = 100, 1000
    
    # log(a*b) = log(a) + log(b)
    left = math.log10(a * b)
    right = math.log10(a) + math.log10(b)
    print(f"log({a}*{b}) = {left:.6f}")
    print(f"log({a}) + log({b}) = {right:.6f}")
    print(f"誤差: {abs(left - right):.2e}\n")
    
    # log(a/b) = log(a) - log(b)
    left = math.log10(a / b)
    right = math.log10(a) - math.log10(b)
    print(f"log({a}/{b}) = {left:.6f}")
    print(f"log({a}) - log({b}) = {right:.6f}")
    print(f"誤差: {abs(left - right):.2e}\n")
    
    # log(a^n) = n * log(a)
    n = 3
    left = math.log10(a ** n)
    right = n * math.log10(a)
    print(f"log({a}^{n}) = {left:.6f}")
    print(f"{n} * log({a}) = {right:.6f}")
    print(f"誤差: {abs(left - right):.2e}")

verify_logarithm_laws()

実践的な応用例

複利計算

import math

def compound_interest(principal, rate, time, compound_frequency=1):
    """
    複利計算
    principal: 元本
    rate: 年利率(小数)
    time: 年数
    compound_frequency: 年間複利回数
    """
    if compound_frequency == float('inf'):  # 連続複利
        return principal * math.exp(rate * time)
    else:
        return principal * (1 + rate/compound_frequency) ** (compound_frequency * time)

# 例:100万円を年利5%で10年間運用
principal = 1000000
rate = 0.05
time = 10

# 年1回複利
annual = compound_interest(principal, rate, time, 1)
print(f"年1回複利: {annual:,.0f}円")

# 連続複利
continuous = compound_interest(principal, rate, time, float('inf'))
print(f"連続複利: {continuous:,.0f}円")

print(f"差額: {continuous - annual:,.0f}円")

人口増加モデル

import math

def exponential_growth(initial_population, growth_rate, time):
    """
    指数成長モデル: P(t) = P₀ * e^(rt)
    """
    return initial_population * math.exp(growth_rate * time)

def logistic_growth(initial_pop, growth_rate, carrying_capacity, time):
    """
    ロジスティック成長モデル
    """
    exp_term = math.exp(growth_rate * time)
    return (carrying_capacity * initial_pop * exp_term) / \
           (carrying_capacity + initial_pop * (exp_term - 1))

# 例:初期人口1000人、成長率2%/年
initial = 1000
rate = 0.02
years = [0, 10, 20, 50, 100]

print("年数 | 指数成長    | ロジスティック成長(K=10000)")
print("-" * 50)

for year in years:
    exp_pop = exponential_growth(initial, rate, year)
    log_pop = logistic_growth(initial, rate, 10000, year)
    print(f"{year:4} | {exp_pop:8.0f}人 | {log_pop:12.0f}人")

半減期計算

import math

def half_life_decay(initial_amount, half_life, time):
    """
    半減期による減衰: N(t) = N₀ * (1/2)^(t/t₁/₂)
    """
    return initial_amount * (0.5) ** (time / half_life)

def decay_constant_from_half_life(half_life):
    """
    半減期から崩壊定数を計算: λ = ln(2) / t₁/₂
    """
    return math.log(2) / half_life

# 炭素14の例(半減期5730年)
initial_c14 = 100  # %
half_life_c14 = 5730

ages = [0, 1000, 5730, 11460, 17190]  # 年

print("年数     | 残存率(%)")
print("-" * 20)

for age in ages:
    remaining = half_life_decay(initial_c14, half_life_c14, age)
    print(f"{age:8} | {remaining:8.2f}")

# 崩壊定数
decay_const = decay_constant_from_half_life(half_life_c14)
print(f"\n炭素14の崩壊定数: {decay_const:.2e} /年")

pH値の計算

import math

def concentration_to_ph(h_concentration):
    """
    水素イオン濃度からpH値を計算: pH = -log₁₀[H⁺]
    """
    if h_concentration <= 0:
        raise ValueError("濃度は正の値である必要があります")
    return -math.log10(h_concentration)

def ph_to_concentration(ph):
    """
    pH値から水素イオン濃度を計算: [H⁺] = 10^(-pH)
    """
    return 10 ** (-ph)

# 様々な溶液のpH値
solutions = [
    ("レモン汁", 1e-2),
    ("コーヒー", 1e-5),
    ("純水", 1e-7),
    ("石鹸水", 1e-10),
    ("アンモニア", 1e-11)
]

print("溶液      | [H⁺] mol/L | pH値")
print("-" * 35)

for name, concentration in solutions:
    ph = concentration_to_ph(concentration)
    print(f"{name:8} | {concentration:10.0e} | {ph:4.1f}")

# pH値から濃度への逆変換
target_ph = 6.5
concentration = ph_to_concentration(target_ph)
print(f"\npH {target_ph}の水素イオン濃度: {concentration:.2e} mol/L")

dB(デシベル)計算

音響・電子工学での応用

import math

def power_to_db(power, reference_power=1):
    """
    電力比をdBに変換: dB = 10 * log₁₀(P/P₀)
    """
    return 10 * math.log10(power / reference_power)

def voltage_to_db(voltage, reference_voltage=1):
    """
    電圧比をdBに変換: dB = 20 * log₁₀(V/V₀)
    """
    return 20 * math.log10(voltage / reference_voltage)

def db_to_power_ratio(db):
    """
    dBから電力比に変換
    """
    return 10 ** (db / 10)

# 音響レベルの例
sound_levels = [
    ("ささやき声", 1e-10),
    ("図書館", 1e-8),
    ("普通の会話", 1e-6),
    ("交通騒音", 1e-3),
    ("ジェット機", 1)
]

print("音源        | 電力密度    | dB値")
print("-" * 35)

reference = 1e-12  # W/m² (聴覚閾値)

for source, power_density in sound_levels:
    db_level = power_to_db(power_density, reference)
    print(f"{source:10} | {power_density:.0e} | {db_level:5.0f}")

エラーハンドリングと数値安定性

定義域外の処理

import math

def safe_log(x, base=math.e):
    """
    安全な対数計算(定義域チェック付き)
    """
    if x <= 0:
        raise ValueError(f"対数の定義域外: x = {x} (x > 0である必要があります)")
    
    if base == math.e:
        return math.log(x)
    elif base == 10:
        return math.log10(x)
    elif base == 2:
        return math.log2(x)
    else:
        if base <= 0 or base == 1:
            raise ValueError(f"不正な底: {base}")
        return math.log(x) / math.log(base)

# テスト
test_values = [-1, 0, 0.5, 1, 10]

for val in test_values:
    try:
        result = safe_log(val, 10)
        print(f"log₁₀({val}) = {result:.3f}")
    except ValueError as e:
        print(f"エラー: {e}")

オーバーフロー/アンダーフローの対策

import math

def safe_exp(x, max_exp=700):
    """
    オーバーフローを防ぐ安全な指数関数
    """
    if x > max_exp:
        return float('inf')
    elif x < -max_exp:
        return 0.0
    else:
        return math.exp(x)

def log_sum_exp(values):
    """
    数値安定なlog-sum-exp計算
    log(sum(exp(x_i))) を安定に計算
    """
    if not values:
        return float('-inf')
    
    max_val = max(values)
    if max_val == float('-inf'):
        return float('-inf')
    
    sum_exp = sum(math.exp(x - max_val) for x in values)
    return max_val + math.log(sum_exp)

# 使用例
large_values = [700, 701, 702]  # 通常のexpではオーバーフロー
result = log_sum_exp(large_values)
print(f"log-sum-exp({large_values}) = {result:.3f}")

まとめ

Pythonの指数・対数関数は以下の特徴を持ちます:

  • 高精度な数値計算
  • 複数の底への対応(e, 10, 2, 任意)
  • 科学技術計算での幅広い応用
  • 適切なエラーハンドリングの重要性

指数・対数関数は、金融計算、人口動態、物理現象、信号処理など、指数的変化や対数スケールが現れる様々な分野で重要な役割を果たします。適切な数値安定性を保ちながら、これらの強力な数学関数を活用しましょう。

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座