[解決!Python]mathモジュールを使ってlog(対数)を計算するには解決!Python

mathモジュールのmath.log関数、math.log1p関数、math.log2関数、math.log10関数を使って対数を求める方法と、それぞれの関数の違いを紹介する。

» 2024年07月16日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「解決!Python」のインデックス

連載目次

import math

# 10の自然対数(eを底とする)を求める
x = 10
result = math.log(x)
print(f'math.log({x}): {result}'# math.log(10): 2.302585092994046

# math.eの自然対数(eを底とする)を求める
x = math.e
result = math.log(x)
print(f'math.log({x}): {result}'# math.log(2.718281828459045): 1.0

# math.log関数で2を底とする対数を求める
x = 0b0100  # 4
base = 2
result = math.log(x, base)
print(f'math.log({x:#0b}, {base}): {result}'# math.log(0b100, 2): 2.0

# math.log関数で10を底とする対数を求める
x = 100
base = 10
result = math.log(x, base)
print(f'math.log({x}, {base}): {result}'# math.log(100, 10): 2.0

# math.log2関数で2を底とする対数を求める
x = 0b0100  # 4
result = math.log2(x)
print(f'math.log2({x:#0b}): {result}'# math.log2(0b100): 2.0

# math.log10関数で10を底とする対数を求める
x = 100
result = math.log10(x)
print(f'math.log10({x}): {result}'# math.log10(100): 2.0

# math.log1p関数で1.000001の自然対数を求める
x = 1.0e-6
print(x)  # 1e-6
print(1+x)  # 1.000001
result0 = math.log1p(x)
result1 = math.log(1+x)
print(result0)  # 9.999995000003334e-07
print(result1)  # 9.999994999180668e-07
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # True

# math.log1p関数で1.000000000001の自然対数を求める
x = 1.0e-12
print(x)  # 1e-12
print(1+x)  # 1.000000000001
result0 = math.log1p(x)
result1 = math.log(1+x)
print(result0)  # 9.999999999995e-13
print(result1)  # 1.000088900581841e-12
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # False

# math.log2関数で底を2とする10の対数を求める
x = 10
result0 = math.log2(x)
result1 = math.log(x, 2)
print(result0)  # 3.321928094887362
print(result1)  # 3.3219280948873626
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # True

# math.log2関数で底を2とするsys.float_info.minの対数を求める
import sys

x = sys.float_info.min
result0 = math.log2(x)
result1 = math.log(x, 2)
print(result0)  # -1022.0
print(result1)  # -1022.0
print(result0 == result1)  # True
print(math.isclose(result0, result1))  # True

# math.log10関数で底を10とする5の対数を求める
x = 5
result0 = math.log10(x)
result1 = math.log(x, 10)
print(result0)  # 0.6989700043360189
print(result1)  # 0.6989700043360187
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # True

# math.log10関数で底を10とするsys.float_info.maxの対数を求める
x = sys.float_info.max
result0 = math.log10(x)
result1 = math.log(x, 10)
print(result0)  # 308.25471555991675
print(result1)  # 308.2547155599167
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # True


関数 説明
math.log(x, base) baseを底とするxの対数を求める。baseを指定しない場合、自然対数を求める
math.log2(x) 2を底とするxの対数を求める。math.log関数よりも正確な値を計算する
math.log10(x) 10を底とするxの対数を求める。math.log関数よりも正確な値を計算する
math.log1p(x) 「1+x」の自然対数を求める。xが0に近くなると(1+xが1に近くなると)math.log関数よりも正確な値を計算する
mathモジュールが提供する対数計算用の関数

対数を求めるさまざまな関数

 Pythonのmathモジュールには対数を求めるための関数が幾つか用意されている。

  • math.log関数
  • math.log2関数
  • math.log10関数
  • math.log1p関数

 最も基本的なのはmath.log関数で、これは対数を求めたい値とその底を指定する。底を指定しないと自然対数が求められる。math.log2関数は2を底とする対数を、math.log10関数は10を底とする対数を求める。math.log1p関数は引数に渡した値(これをxとする)に1を足した「1+x」の自然対数を求めるのに使用する。ドキュメントによれば、これら3つの関数はmath.log関数よりも正確に対数を求められる。

 最も基本的なmath.log関数の使用例を以下に示す。

import math

# 10の自然対数(eを底とする)を求める
x = 10
result = math.log(x)
print(f'math.log({x}): {result}'# math.log(10): 2.302585092994046

# math.eの自然対数(eを底とする)を求める
x = math.e
result = math.log(x)
print(f'math.log({x}): {result}'# math.log(2.718281828459045): 1.0


 math.log関数は2つの値を引数に指定可能で、第2引数(base)は省略可能だ。その場合はネイピア数eを底とする対数(自然対数)を計算する。1つ目の例は対数を求める値として10を指定して、底(base)を指定していないので10の自然対数が求められる。2つ目の例では対数を求める値としてmath.e(ネイピア数)を指定して、底(base)を指定していないので、その答えが1となっている(e1の自然対数は1)。

 次にmath.log関数に底として2を指定する例を示す。

x = 0b0100  # 4
base = 2
result = math.log(x, base)
print(f'math.log({x:#0b}, {base}): {result}'# math.log(0b100, 2): 2.0


 対数を求める値としては「0b0100」を指定して、第2引数(base)には底として2を指定している。対数を求める値は22=「4」なのでその答え(2を底とする対数)は2.0となる。

 同様にmath.log関数に底として10を指定する例を以下に示す。

x = 100
base = 10
result = math.log(x, base)
print(f'math.log({x}, {base}): {result}'# math.log(100, 10): 2.0


 上と同様に100は102なので、10を底とするこの値の対数は2.0となる。

 math.log2関数とmath.log10関数は、底をそれぞれ2、10に固定して対数を求めるものだ。以下に使用例を示す。

x = 0b0100  # 4
result = math.log2(x)
print(f'math.log2({x:#0b}): {result}'# math.log2(0b100): 2.0

x = 100
result = math.log10(x)
print(f'math.log10({x}): {result}'# math.log10(100): 2.0


 これらについては特に説明の必要はないだろう。

より正確な対数を求める

 math.log2関数、math.log10関数、math.log1p関数はmath.log関数よりも正確に対数を求められる。そこでこれらの関数を使ったときとmath.log関数を使ったときとで計算結果に差が出るかどうかを簡単に調べてみよう。まずはmath.log1p関数から。

 math.log1p関数は引数に渡した値(x)に1を加算した値の自然対数を求める。xが0に近くなるとmath.log関数よりも対数を正確に計算できる。そこで、xに0.000001(1e-6)を渡してみると、つまり1.000001の自然対数を求めるとどうなるだろう。以下にその結果を示す。

x = 1.0e-6
print(x)  # 1e-6
print(1+x)  # 1.000001
result0 = math.log1p(x)
result1 = math.log(1+x)
print(result0)  # 9.999995000003334e-07
print(result1)  # 9.999994999180668e-07
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # True


 変数result0にはmath.log1p関数に0.000001を渡して、1.000001の自然対数を計算した結果が代入されている。変数result1にはmath.log関数を使って求めた結果が代入されている。2つのprint関数の出力結果から分かる通り、その値は異なる。また、==演算子による比較でも2つの値(1.000001の自然対数)が異なっていることが分かる。ただし、math.isclose関数を使って両者が近い値かどうかを調べてみるとTrueとなっている。

 次にさらにxを0に近い値としてみる。ここでは1e-12(0.000000000001)を渡してみる。

x = 1.0e-12
print(x)  # 1e-12
print(1+x)  # 1.000000000001
result0 = math.log1p(x)
result1 = math.log(1+x)
print(result0)  # 9.999999999995e-13
print(result1)  # 1.000088900581841e-12
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # False


 すると今度は2つの値は異なり、さらにmath.isclose関数の結果もFalseとなった。

 次に2を底とする対数についても同様に調べてみよう。以下は2を底とする10の対数の計算例だ。

x = 10
result0 = math.log2(x)
result1 = math.log(x, 2)
print(result0)  # 3.321928094887362
print(result1)  # 3.3219280948873626
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # True


 ここでも2つの計算結果は異なるが、2つの値は近いと判断されている。

 以下では浮動小数点数値の最小値(sys.float_info.min)を与えて、2を底とするその対数を求めている。

import sys

x = sys.float_info.min
result0 = math.log2(x)
result1 = math.log(x, 2)
print(result0)  # -1022.0
print(result1)  # -1022.0
print(result0 == result1)  # True
print(math.isclose(result0, result1))  # True


 こちらについても、2つの計算結果は異なるが、近い値が得られている。

 math.log10関数についても同様だ。以下に例を示す。

# math.log10関数で底を10とする5の対数を求める
x = 5
result0 = math.log10(x)
result1 = math.log(x, 10)
print(result0)  # 0.6989700043360189
print(result1)  # 0.6989700043360187
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # True

# math.log10関数で底を10とするsys.float_info.maxの対数を求める
x = sys.float_info.max
result0 = math.log10(x)
result1 = math.log(x, 10)
print(result0)  # 308.25471555991675
print(result1)  # 308.2547155599167
print(result0 == result1)  # False
print(math.isclose(result0, result1))  # True


 対数を求めるには通常はmath.log関数を使えばよいが、より正確な値を求めたいのであればmath.log1p関数、math.log2関数、math.log10関数を使えることは覚えておこう。

「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。