結論

自然対数とは、ネイピア数 e(2.718281828…)を底とする対数で、ln x と書きます。「e を何乗すると x になるか」を表し、e の x 乗(指数関数 exp)のちょうど逆の計算です。プログラミング言語の log() はほとんどが自然対数ですが、PostgreSQL と SQLite の log() は常用対数(底10)です。

この記事でわかること

  • e と ln の意味、対数法則・微分・積分・常用対数との変換を、計算した数値で確かめた結果
  • Python・JavaScript・Java・C・Go・Rust・Ruby・PHP と SQL の log・log10・log1p の違いと、0や負の数を渡したときのエラー原文
  • (1+1/n) の n 乗が 1.0 になってしまう桁落ちと、log1p・logsumexp で直した実測、複利・対数損失での使われ方

2026年10月29日更新|Python 3.13・Node.js 22・Java 21・gcc 13・Go 1.24・Rust 1.97・PostgreSQL 16 で実行して確認

この記事で実際に動かしたもの:Ubuntu 24.04 の上で、8つのプログラミング言語の対数関数、SQLite 3.53 と作業用に立てた PostgreSQL 16(127.0.0.1 のみ)の ln・log、awk・bc、NumPy・SciPy・scikit-learn による桁落ち・対数損失・logsumexp の計算。

自然対数・e・指数関数の関係を先に図にします。

flowchart TD
    A[x を決める] -->|e の x 乗 exp| B[y = e の x 乗]
    B -->|自然対数 ln| A
    C[ln 1 = 0] --- D[ln e = 1]
    D --- E[ln 10 = 2.302585]

よく調べられることの答えを先にまとめます。

知りたいこと 答え 詳しい節
自然対数とは e を底とする対数。ln x は「e を何乗すると x になるか」 自然対数とは
ln とは logarithmus naturalis(ラテン語で自然対数)の略。ln x = logₑ x 自然対数とは
自然対数の底 e の値 2.718281828459045…(終わりのない無理数) ネイピア数eとは
ln 2・ln 10 はいくつ ln 2 = 0.693147、ln 10 = 2.302585 自然対数の性質と公式
常用対数との違い・変換 常用対数は底10。ln x = 2.302585 × log₁₀ x 自然対数と常用対数の違い
log は自然対数? 高校数学・Python・JavaScript は自然対数。PostgreSQL・SQLite の log() は底10 場面で違う log の意味
log(0) がエラーになる 0以下の自然対数は実数では定義されない。言語ごとに例外・-Infinity・NaN 0・負の数のエラー原文
log1p はなぜあるのか x が小さいと log(1+x) は桁落ちする。x=1e-15 で11%ずれた log1pが要る理由

確認環境:Ubuntu 24.04.5 LTS(2 CPU)。作業用のフォルダーで、Python 3.13.18(NumPy 2.5.3・SciPy 1.18.1・scikit-learn 1.9.1)、Node.js 22.23.4、OpenJDK 21.0.12.1、gcc 13.3.0(glibc の libm)、Go 1.24.7、Rust 1.97.0、Ruby 3.3.6、PHP 8.3.6、mawk 1.3.4、bc 1.07.1、SQLite 3.53.1(Python の sqlite3)を実行しました。PostgreSQL 16.15 は作業用のフォルダーにデータベースを作り、127.0.0.1 だけで起動して t208db で関数を試し、終わってから削除して停止しています。MySQL は手元で動かしておらず、MySQL 8.4 リファレンスマニュアルの関数の説明で書きました。真の値との比較には Python 標準の decimal(50〜60桁)を使っています。各言語の関数の仕様は、Python・MDN・Oracle(Java 21)・PostgreSQL・SQLite・MySQL の公式ドキュメントで確かめました。図は mermaid-cli で描画を確かめています(確認日 2026年10月29日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「自然対数とは?eとlnの意味・log1pが要る理由を8言語で実測」

自然対数とは(eを底とする対数・lnの意味)

この節では、自然対数の定義と、ln という記号の読み方・書き方が分かります。

自然対数は、底が e(ネイピア数、約 2.71828)の対数です。x の自然対数を ln x と書き、「e を何乗すると x になるか」という数を表します。たとえば e を 2.302585 乗すると 10 になるので、ln 10 = 2.302585 です。

対数(logarithm)は「ある数を何乗すると目的の数になるか」を表す数です。底が 2 なら log₂ 8 = 3(2 を3乗すると8)、底が 10 なら log₁₀ 1000 = 3(10 を3乗すると1000)です。このうち、底を e にしたものを自然対数、底を 10 にしたものを常用対数と呼びます。

1書き方

ln x・logₑ x・log x(底を省いた形)。ln は logarithmus naturalis の頭文字。読みは「エルエヌ」「ログ」「ナチュラルログ」。

2指数関数の逆

ln(e の x 乗) = x、e の (ln x) 乗 = x(x > 0)。exp でかけた「何乗」を取り出す計算。

3覚えておく値

ln 1 = 0、ln e = 1、ln 2 ≒ 0.693、ln 10 ≒ 2.303。0以下の数には実数の自然対数が無い。

Python で確かめると、次のとおりです。math.log() に引数を1つだけ渡すと自然対数になります。

import math
print("math.e      =", math.e)
print("math.log(math.e) =", math.log(math.e))
print("math.log(1)      =", math.log(1))
for x in [2, 7.5, 10, 100]:
    print(f"math.log({x}) = {math.log(x)!r}")
print("math.exp(math.log(5)) =", math.exp(math.log(5)))
math.e      = 2.718281828459045
math.log(math.e) = 1.0
math.log(1)      = 0.0
math.log(2) = 0.6931471805599453
math.log(7.5) = 2.0149030205422647
math.log(10) = 2.302585092994046
math.log(100) = 4.605170185988092
math.exp(math.log(5)) = 4.999999999999999

ln 100 が ln 10 のちょうど2倍(4.605170…)になっているのは、100 = 10 × 10 だからです(積の対数は対数の和)。最後の行が 5 ではなく 4.999999999999999 になるのは、コンピューターの小数(浮動小数点数)の丸め誤差です。数学では e の (ln 5) 乗 = 5 ですが、プログラムでは最後の桁がずれることがあります。小数の誤差の仕組みは、関連記事「浮動小数点数とは|仕組み・誤差・0.1+0.2の理由を4言語で実演」で扱っています。

なお、Unicode には自然対数専用の1文字「㏑」(U+33D1、名前は SQUARE LN)もあります。Python の unicodedata.name("㏑") で SQUARE LN と出ることを確かめました。数式やプログラムでは、ふつうの英字2文字で ln と書きます。

ネイピア数eとは(値と2つの求め方を計算で確かめる)

この節では、自然対数の底 e がどんな数で、どうやって求めるのかが、計算結果で分かります。

e は「(1 + 1/n) の n 乗」で n を限りなく大きくしたときに近づく数で、2.718281828459045… と終わりなく続く無理数です。発見に関わった数学者の名前からネイピア数、または「オイラーの数」とも呼ばれます。同じ値は 1 + 1/1! + 1/2! + 1/3! + …(階乗の逆数の和)でも求められます。

(1 + 1/n) の n 乗で近づける

import math
for k in [1,2,3,4,6,8,10,12,14,15,16,17]:
    n = 10**k
    v = (1 + 1/n)**n
    print(f"n=1e{k:<2} {v:.15f}  err={abs(v-math.e):.2e}")
n=1e1  2.593742460100002  err=1.25e-01
n=1e2  2.704813829421528  err=1.35e-02
n=1e3  2.716923932235594  err=1.36e-03
n=1e4  2.718145926824926  err=1.36e-04
n=1e6  2.718280469095753  err=1.36e-06
n=1e8  2.718281798347358  err=3.01e-08
n=1e10 2.718282053234788  err=2.25e-07
n=1e12 2.718523496037238  err=2.42e-04
n=1e14 2.716110034087023  err=2.17e-03
n=1e15 3.035035206549262  err=3.17e-01
n=1e16 1.000000000000000  err=1.72e+00
n=1e17 1.000000000000000  err=1.72e+00

n = 1億(1e8)までは e に近づきますが、そこから先は逆に離れ、n = 1e16 では 1.0 になりました。数学の誤りではなく、コンピューターの小数では 1 + 1e-16 が 1 と同じ値に丸められるためです(倍精度で 1 の次に表せる数は 1 + 2.22e-16)。1 を何乗しても 1 なので、結果が 1.0 になります。同じ式を Python の decimal(50桁)で計算すると、n = 1e16 で 2.718281828459045099 と正しく近づきました。この現象は後の「log1pが要る理由」の節で、log1p を使って直します。

階乗の逆数の和で近づける

k<=  0: 1.0000000000000000 err=1.7e+00
k<=  1: 2.0000000000000000 err=7.2e-01
k<=  2: 2.5000000000000000 err=2.2e-01
k<=  3: 2.6666666666666665 err=5.2e-02
k<=  5: 2.7166666666666663 err=1.6e-03
k<=  8: 2.7182787698412700 err=3.1e-06
k<= 12: 2.7182818282861687 err=1.7e-10
k<= 15: 2.7182818284589949 err=5.0e-14
k<= 17: 2.7182818284590455 err=4.4e-16

階乗の和は 18 項(k = 0〜17)で倍精度の限界(誤差 4.4e-16)まで届きました。(1 + 1/n) の n 乗では1億回かけても8桁しか合わないのと比べると、近づく速さがまったく違います。各言語の Math.E・math.e などの定数は、あらかじめ倍精度でいちばん近い値が入っているので、自分で計算する場面はほとんどありません。

2.718281828…e の値bc -l で40桁:2.7182818284590452353602874713526624977572
18項階乗の和で倍精度の限界へ誤差 4.4e-16
1e16(1+1/n) の n 乗が 1.0 になる n1+1e-16 が 1 に丸まるため

自然対数のグラフと性質・公式(対数法則・微分・積分)

この節では、y = ln x のグラフの形と、自然対数の公式(対数法則・微分・積分・級数)を、数値で確かめた結果とともに分かります。

y = ln x は、x = 1 で 0 を通り、x が大きくなるとゆっくり増え続け、x が 0 に近づくと −∞ へ下がる曲線です。y 軸(x = 0)は漸近線で、x ≦ 0 の部分はありません。y = e の x 乗のグラフを、直線 y = x で折り返した形です。

x ln x(計算値) 読み方
0.5−0.6931471より小さいと負になる
10e の0乗 = 1
20.693147倍にすると 0.693 増える
e(2.71828)1e の1乗 = e
102.30258510倍ごとに 2.303 増える
10006.9077551000 でもまだ 7 弱
10 の 400 乗921.034037Python の整数ならあふれずに計算できた

最後の行は、Python の math.log(10**400) の結果です。10 の 400 乗は倍精度の小数では表せない(約 1.8e308 が上限)のですが、Python の math.log は大きな整数をそのまま受け取って 921.034… を返しました。

対数法則と公式

  • 1積は和になる:ln(xy) = ln x + ln yln 100 = 4.605170 は ln 10 = 2.302585 の2倍
  • 2商は差になる:ln(x/y) = ln x − ln yln 0.5 = ln 1 − ln 2 = −0.693147
  • 3累乗はかけ算になる:ln(x の r 乗) = r × ln xln(2 の 1000 乗) = 693.147…(Python で確認)
  • 4微分は 1/x:(ln x)′ = 1/x差分 (ln(x+h) − ln x)/h、h=1e-6 で x=2 は 0.49999988
  • 5積分:∫(1/x)dx = ln|x| + C、∫ln x dx = x ln x − x + C1 から e までの ∫ln x dx は 1
  • 6級数:ln(1+x) = x − x²/2 + x³/3 − …(−1 < x ≦ 1)x が小さいほど少ない項で合う

「1/x のグラフの面積」としての自然対数

自然対数は、y = 1/x のグラフの下の、1 から a までの面積として定義することもできます(a < 1 なら面積に負の符号を付ける)。微分が 1/x になるのは、この定義の裏返しです。面積を100万本の台形に分けて足し、ln a と比べました。

a=2 area=0.6931471806 ln(a)=0.6931471806
a=2.71828 area=1.0000000000 ln(a)=1.0000000000
a=10 area=2.3025850930 ln(a)=2.3025850930
a=0.5 area=-0.6931471806 ln(a)=-0.6931471806

面積がちょうど 1 になる a が e です。「自然」と呼ばれるのは、このように微分・積分・級数の式が最も簡単な形になる底だからです。常用対数(底10)は、私たちが十進法を使っているという、人間側の都合で選ばれた底です。

ln(1+x) の級数はどれくらいで合うか

x=0.1 ln=0.0953101798 1:4.7e-03 2:3.1e-04 3:2.3e-05 5:1.5e-07 10:8.3e-13 100:1.4e-17
x=0.5 ln=0.4054651081 1:9.5e-02 2:3.0e-02 3:1.1e-02 5:1.8e-03 10:3.0e-05 100:1.1e-16
x=1.0 ln=0.6931471806 1:3.1e-01 2:1.9e-01 3:1.4e-01 5:9.0e-02 10:4.8e-02 100:5.0e-03 1000:5.0e-04

「項数:誤差」の並びです。x = 0.1 では10項で誤差 8.3e-13 ですが、x = 1(ln 2)では1000項足しても誤差 5.0e-04 でした。ライブラリの log 関数は、この級数をそのまま足しているのではなく、x を小さな範囲に変形してから計算しています。x が小さいときに ln(1+x) ≒ x と近似できる(1項目だけで合う)ことは、log1p や複利の計算で使います。

自然対数と常用対数の違い・変換(ln と log10)

この節では、自然対数と常用対数(底10)の違いと、両者を変換する式が分かります。

自然対数と常用対数は底が違うだけで、値は一定の比になります。ln x = 2.302585 × log₁₀ x、log₁₀ x = 0.434294 × ln x です。2.302585 は ln 10、0.434294 は log₁₀ e(= 1/ln 10)です。

自然対数(ln、底 e)

微分・積分・級数の式が簡単

連続的な成長・減衰、確率、機械学習

多くの言語の log()

常用対数(log₁₀、底10)

桁数と対応する(log₁₀ 1000 = 3)

pH・デシベル・マグニチュード

log10()、PostgreSQL・SQLite の log()

変換は「底の変換公式」logₐ x = ln x ÷ ln a から出ます。よく出る例題で確かめます。

import math
x = 2.0
print("log10(2)*ln10 =", math.log10(x)*math.log(10), " ln2 =", math.log(x))
print("0.3010*2.303 =", 0.3010*2.303)
print("ln10 =", math.log(10), " 1/ln10 =", 1/math.log(10))
log10(2)*ln10 = 0.6931471805599454  ln2 = 0.6931471805599453
0.3010*2.303 = 0.6932029999999999
ln10 = 2.302585092994046  1/ln10 = 0.43429448190325176

手計算で習う「log₁₀ 2 ≒ 0.3010 に 2.303 をかける」方法では 0.6932 となり、本当の ln 2 = 0.693147 と4桁目まで合います。プログラムで変換すると最後の1桁(1e-16 の位)がずれることがあるため、log10・log2 が用意されている言語では、変換せずにその関数を使うのが正確です。この差は次の節で実測します。

2を底とする対数(log₂)も同じ関係で、log₂ x = 1.442695 × ln x です。アルゴリズムの計算量 O(log n) は、底が違っても定数倍しか変わらないので、底を書かずに表します。n = 100万のとき log₂ n = 19.93、ln n = 13.82 で、比は常に 1.442695(= 1/ln 2)でした。二分探索なら約20回で見つかる、という数え方は log₂ を使っています。

logは自然対数?常用対数?場面で違うlogの意味

この節では、底を省いた「log」が、分野・ツールによって自然対数を指すのか常用対数を指すのかが一覧で分かります。

底を書かない log x は、数学(高校・大学)と多くのプログラミング言語では自然対数、データベースの一部・工学の一部・電卓では常用対数です。同じ「log」でも、どこで書かれたかで値が 2.3 倍違うので、資料やコードを読むときは最初に確かめます。

場面 log x の意味 自然対数の書き方 確かめた方法
高校数学(数学Ⅲ)自然対数(微分・積分の単元)log x上位の解説記事と教科書の慣例
工学・物理の資料常用対数のことが多いln x一般的な慣例(資料ごとに確認)
関数電卓log キー=常用対数ln キー一般的な配列
Python・JavaScript・Java・C・Go・Ruby・PHP自然対数log()実行して ln 10 = 2.302585 を確認
Rustlog(base) は底を必ず指定ln()実行して確認
PostgreSQL・SQLite常用対数(底10)ln()実行して log(100) = 2 を確認
MySQL自然対数(1引数のとき)LN() または LOG()MySQL 8.4 公式マニュアル
awk・bcawk の log() は自然対数awk は log()、bc -l は l()実行して確認

情報理論ではビット(底2)、統計や機械学習では自然対数(単位はナット)を使うのがふつうです。エントロピーの単位の違いは、関連記事「エントロピーとは|意味・計算・交差エントロピーをPythonで実演」で扱っています。

プログラミング言語の自然対数:8言語のlog・log10・log1p

この節では、Python・JavaScript・Java・C・Go・Rust・Ruby・PHP で、自然対数と関連の関数をどう書くかと、実行結果が分かります。

8言語とも、自然対数・常用対数・log1p(1+x の自然対数)はそろっていましたが、名前と「底を指定する方法」が違います。Java には log2 がありません。

言語 自然対数 底10・底2 任意の底 log1p
Pythonmath.log(x)math.log10・math.log2math.log(x, b)math.log1p
JavaScriptMath.log(x)Math.log10・Math.log2無し(割り算)Math.log1p
JavaMath.log(x)Math.log10(log2 は無し)無し(割り算)Math.log1p
Clog(x)log10・log2無し(割り算)log1p
Gomath.Log(x)math.Log10・math.Log2無し(割り算)math.Log1p
Rustx.ln()x.log10()・x.log2()x.log(b)x.ln_1p()
RubyMath.log(x)Math.log10・Math.log2Math.log(x, b)無し(標準の Math に無い)
PHPlog(x)log10(log2 は無し)log(x, b)log1p

JavaScript

console.log("Math.E =", Math.E);
console.log("Math.log(10) =", Math.log(10));
console.log("Math.log10(1000) =", Math.log10(1000), " Math.log2(8) =", Math.log2(8));
console.log("Math.log(1000)/Math.LN10 =", Math.log(1000) / Math.LN10);
console.log("Math.log1p(1e-15) =", Math.log1p(1e-15), " Math.log(1+1e-15) =", Math.log(1 + 1e-15));
console.log("Math.log(0) =", Math.log(0), " Math.log(-1) =", Math.log(-1), ' Math.log("e") =', Math.log("e"));
Math.E = 2.718281828459045
Math.log(10) = 2.302585092994046
Math.log10(1000) = 3  Math.log2(8) = 3
Math.log(1000)/Math.LN10 = 2.9999999999999996
Math.log1p(1e-15) = 9.999999999999995e-16  Math.log(1+1e-15) = 1.110223024625156e-15
Math.log(0) = -Infinity  Math.log(-1) = NaN  Math.log("e") = NaN

底を割り算で変えると、log₁₀ 1000 が 3 ではなく 2.9999999999999996 になりました。Python の math.log(1000, 10) も同じ 2.9999999999999996 で、Python の公式ドキュメントにも「2引数の log は log(x)/log(base) で計算する」「log10 は log(x, 10) より通常は正確」と書かれています。Math.floor() や int() で桁数を求めると 2 になってしまうので、桁数を出すときは log10 を使います。

Java

public class Ln {
  public static void main(String[] a) {
    System.out.println("Math.E = " + Math.E);
    System.out.println("Math.log(10) = " + Math.log(10));
    System.out.println("Math.log10(1000) = " + Math.log10(1000));
    System.out.println("log2(1<<29) = " + Math.log(1 << 29) / Math.log(2));
    System.out.println("Math.log(0) = " + Math.log(0) + "  Math.log(-1) = " + Math.log(-1));
    System.out.println("31 - numberOfLeadingZeros(8) = " + (31 - Integer.numberOfLeadingZeros(8)));
  }
}
Math.E = 2.718281828459045
Math.log(10) = 2.302585092994046
Math.log10(1000) = 3.0
log2(1<<29) = 29.000000000000004
Math.log(0) = -Infinity  Math.log(-1) = NaN
31 - numberOfLeadingZeros(8) = 3

Java の Math には log2 が無いため、Math.log(x) / Math.log(2) と書く例をよく見ます。2 の 29 乗で試すと 29.000000000000004 になりました。整数の log₂(何ビット目が最上位か)なら、31 - Integer.numberOfLeadingZeros(x) のように整数の演算で求めると誤差が出ません。

C・Go・Rust

#include <stdio.h>
#include <math.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
    double x = atof(argc > 1 ? argv[1] : "10");
    printf("log(%g) = %.17g\n", x, log(x));
    printf("log1p(1e-15) = %.17g  log(1+1e-15) = %.17g\n", log1p(1e-15), log(1 + 1e-15));
    errno = 0; double z = log(x - x);  printf("log(0)  = %g  errno=%d (%s)\n", z, errno, strerror(errno));
    errno = 0; double n = log(-x);     printf("log(-%g) = %g  errno=%d (%s)\n", x, n, errno, strerror(errno));
    return 0;
}
$ gcc ln.c -o ln
/usr/bin/ld: /tmp/ccwambLv.o: in function `main':
ln.c:(.text+0x46): undefined reference to `log'
/usr/bin/ld: ln.c:(.text+0x7b): undefined reference to `log2'
/usr/bin/ld: ln.c:(.text+0x8e): undefined reference to `log10'
$ gcc ln.c -o ln -lm && ./ln 10
log(10) = 2.3025850929940459
log1p(1e-15) = 9.9999999999999949e-16  log(1+1e-15) = 1.1102230246251559e-15
log(0)  = -inf  errno=34 (Numerical result out of range)
log(-10) = -nan  errno=33 (Numerical argument out of domain)

C(gcc と glibc)では、数学ライブラリを -lm でリンクしないと undefined reference to `log' になります。定数だけの log(10.0) はコンパイル時に計算されてエラーにならないことがあるので、上の例では値を実行時に受け取っています。C の log は例外を投げず、errno に ERANGE(0のとき)・EDOM(負のとき)を入れて返ります。

Go:   math.Log(10) = 2.302585092994046   math.Log1p(1e-15) = 9.999999999999995e-16
      math.Log(0) = -Inf   math.Log(-1) = NaN
Rust: x.ln() = 2.302585092994046   8f64.log(2.0) = 3   1e-15f64.ln_1p() = 0.0000000000000009999999999999995
      0f64.ln() = -inf   (-1f64).ln() = NaN

Rust だけは「ln」という名前を使い、log() は底を引数に取ります。数学の書き方に近く、取り違えが起きにくい名前です。

Ruby・PHP・awk・bc

$ ruby -e 'puts Math.log(10); puts Math.log(8, 2); begin; Math.log(-1); rescue => e; puts "#{e.class}: #{e.message}"; end; puts Math.log(0)'
2.302585092994046
3.0
Math::DomainError: Numerical argument is out of domain - log
-Infinity
$ php -r 'echo log(10),"\n", log(8,2),"\n", log1p(1e-15),"\n"; var_dump(log(0), log(-1));'
2.302585092994
3
1.0E-15
float(-INF)
float(NAN)
$ awk 'BEGIN{printf "awk log(10)=%.15g exp(1)=%.15g\n", log(10), exp(1)}'
awk log(10)=2.30258509299405 exp(1)=2.71828182845905
$ echo 'l(10); e(1)' | bc -l
2.30258509299404568401
2.71828182845904523536

PHP は echo で表示すると桁が丸められて 2.302585092994 と見えますが、中の値は他の言語と同じ倍精度です。シェルで手早く自然対数を出したいときは、awk の log() か bc -l の l() が使えます。bc は scale=40 で40桁まで計算できました。Python の math モジュールの他の関数は、関連記事「Python mathモジュールの使い方|切り上げ・切り捨て・平方根と関数一覧」で扱っています。

SQLの自然対数:PostgreSQL・SQLite・MySQLでlog()の底が違う

この節では、SQL で自然対数を求める関数と、データベースごとに log() の底が違う落とし穴が分かります。

SQL で自然対数を求めるときは、どのデータベースでも ln() を使うのが確実です。log(x) は PostgreSQL と SQLite では常用対数、MySQL では自然対数で、同じ SQL が別の値を返します。

-- PostgreSQL 16.15(127.0.0.1 の作業用データベース t208db)
select ln(10)        -> 2.302585092994046
select log(100)      -> 2
select log(2, 8)     -> 3.0000000000000000
select log10(100)    -> 2
select exp(1)        -> 2.718281828459045
select ln(0)         -> ERROR:  cannot take logarithm of zero
select ln(-1)        -> ERROR:  cannot take logarithm of a negative number

-- SQLite 3.53.1(Python の sqlite3、:memory:)
select ln(10)        -> 2.302585092994046
select log(100)      -> 2.0
select log(2, 8)     -> 3.0
select ln(0)         -> None(NULL)
select ln(-1)        -> None(NULL)
データベース log(x) 自然対数 0・負の数
PostgreSQL底10ln(x)エラー(上の原文)
SQLite底10ln(x)NULL
MySQL自然対数ln(x) または log(x)NULL と警告「Invalid argument for logarithm」(公式)

SQLite の公式ドキュメントには「log() は PostgreSQL と同じく底10」と書かれており、数学関数はビルド時の SQLITE_ENABLE_MATH_FUNCTIONS で有効になる、とあります。手元の Python に入っている SQLite では有効でしたが、組み込み機器などで使う SQLite では no such function: ln になる場合があります。2引数の log(b, x) は3つとも「第1引数が底」で、Python の math.log(x, base) とは引数の順番が逆です。

データベースを移行するときの log()

やってはいけないMySQL の LOG(x) をそのまま PostgreSQL に持っていく。エラーにならず、値だけが 1/2.3 倍になる
↔
代わりに自然対数は LN(x)、常用対数は LOG10(x) と、底が名前で分かる関数に書き換える

3つのデータベースすべてで同じ値になる書き方

自然対数の「0・負の数」エラー原文(よくあるエラー)

この節では、自然対数に0や負の数を渡したとき、言語・ツールごとに何が起きるかが、エラーの原文で分かります。

0以下の数の自然対数は、実数の範囲では定義されません。そのとき例外を投げるか、-Infinity・NaN・NULL を返すかは言語によって違い、例外を投げない言語では計算がそのまま進んで、後で別の場所がおかしくなります。

環境 log(0) log(-1) 直し方
Python math(3.13)ValueError: math domain errorValueError: math domain error渡す前に x > 0 を確かめる
NumPy-inf と RuntimeWarning: divide by zero encountered in lognan と RuntimeWarning: invalid value encountered in lognp.log の where= か、np.clip で下限を付ける
JavaScript・Java・Go・Rust-Infinity(-Inf・-inf)NaN結果を Number.isFinite などで確かめる
C(glibc)-inf、errno=34(ERANGE)-nan、errno=33(EDOM)errno か isfinite() を見る
Ruby-InfinityMath::DomainError: Numerical argument is out of domain - logrescue で受ける
PostgreSQLERROR: cannot take logarithm of zeroERROR: cannot take logarithm of a negative numberWHERE x > 0 か NULLIF
SQLiteNULLNULLNULL を集計から外す扱いに注意

他にもよく出るエラーがあります。

>>> math.exp(1000)
OverflowError: math range error
>>> math.log("2")
TypeError: must be real number, not str
>>> np.exp(1000.0)
RuntimeWarning: overflow encountered in exp
inf

e の 1000 乗は倍精度の上限(約 1.8e308)を超えるので、Python の math は OverflowError、NumPy は警告を出して inf を返します。負の数の対数が本当に必要な場合(複素数の計算)は cmath.log(-1) を使うと 3.141592653589793j(πi)が返ります。複素数の自然対数は無数の値をとる(2πi ずつずれる)ため、ライブラリは主値(虚部が −π より大きく π 以下)を返します。

NumPy で0を含む配列の対数をとるときは、計算する場所を where= で選べます。

import numpy as np
x = np.array([0.0, 2.0])
print(np.log(x, where=x > 0, out=np.full(2, -99.0)))
[-99.           0.69314718]

log1pが要る理由:log(1+x)の桁落ちを実測

この節では、log1p・expm1 という関数がなぜ用意されているのかと、使わないとどれだけずれるのかが実測で分かります。

x が 0 に近いとき、log(1 + x) は 1 + x を計算した時点で x の下の桁が失われ、結果が大きくずれます。log1p(x) は 1 を足さずに ln(1 + x) を計算するので、どんなに小さい x でも正確です。

import math
from decimal import Decimal, getcontext
getcontext().prec = 60
for x in [1e-3,1e-6,1e-8,1e-10,1e-12,1e-15,1e-16,1e-20]:
    ref = (Decimal(1)+Decimal(x)).ln()
    a = math.log(1+x); b = math.log1p(x)
    ea = abs((Decimal(a)-ref)/ref); eb = abs((Decimal(b)-ref)/ref)
    print(f"x={x:.0e} log(1+x)={a:.6e} rel={float(ea):.1e} | log1p={b:.6e} rel={float(eb):.1e}")
x log(1+x) の値 log(1+x) の相対誤差 log1p(x) の相対誤差
1e-39.995003e-041.1e-133.9e-17
1e-69.999995e-078.2e-116.6e-17
1e-81.000000e-086.1e-094.8e-17
1e-101.000000e-108.3e-083.4e-17
1e-121.000089e-128.9e-052.4e-17
1e-151.110223e-151.1e-01(11%)9.2e-17
1e-1601.0(100%)5.0e-17

x = 1e-15 で 11%、x = 1e-16 では答えが 0 になり 100% ずれました。log1p は全部の行で誤差 1e-16 程度(倍精度の限界)でした。JavaScript・Java・C・Go・Rust・PHP でも、log(1+1e-15) は 1.110223024625156e-15、log1p は 9.999999999999995e-16 と、言語に関係なく同じ結果になっています。原因は言語ではなく、倍精度の小数そのものにあるからです。

e の計算が 1.0 になった問題を直す

前の節で (1 + 1/n) の n 乗 が n = 1e16 で 1.0 になったのも同じ原因です。a の n 乗 = e の (n × ln a) 乗 を使い、ln(1 + 1/n) を log1p で計算し直しました。

n=1e8: pow=2.718281798347358  exp(n*log1p(1/n))=2.718281814867637
n=1e12: pow=2.718523496037238  exp(n*log1p(1/n))=2.718281828457686
n=1e15: pow=3.035035206549262  exp(n*log1p(1/n))=2.718281828459044
n=1e16: pow=1.000000000000000  exp(n*log1p(1/n))=2.718281828459045
n=1e20: pow=1.000000000000000  exp(n*log1p(1/n))=2.718281828459045

log1p を使った式は、n をどれだけ大きくしても e に近づき続けました。逆向きの exp(x) − 1 にも同じ問題があり、expm1(x) が用意されています。x = 1e-15 で exp(x)-1 は 1.1102230246e-15、expm1 は 1.0000000000e-15 でした。

  1. 1log(1 + 小さい数) を書いている → log1p(小さい数)利率・確率の補数・変化率
  2. 2exp(小さい数) − 1 を書いている → expm1(小さい数)連続複利の利息・成長率
  3. 3log(1 − p) で p が小さい → log1p(−p)生存確率・失敗しない確率
  4. 4a の n 乗で n が巨大 → exp(n × log1p(a − 1))上の e の計算と同じ形

速さの差は小さく、Python で 100万回呼ぶと math.log が 62.8ms、math.log1p が 76.9ms でした。正確さを考えると、x が小さくなりうる場所では log1p を選ぶ理由のほうが大きいといえます。

複利と自然対数:連続複利・72の法則

この節では、e と自然対数が複利の計算でどう出てくるかと、「72の法則」がどれくらい正確かが分かります。

年利100%で、利息を付ける回数を細かくしていくと、1年後の金額は元本の e 倍(2.71828…倍)に近づきます。e が「成長の自然な単位」と呼ばれる理由です。

利息を付ける回数 回数 n 1年後の倍率
年1回12.0000000000
半年ごと22.2500000000
毎月122.6130352902
毎日3652.7145674820
毎時8,7602.7181266916
毎秒31,536,0002.7182817785
連続(極限)∞2.7182818285(= e)

現実的な例として、100万円を年3%で10年預けた場合を計算しました。年1回の複利で 1,343,916円、毎月で 1,349,354円、毎日で 1,349,842円、連続複利(100万 × e の 0.3 乗)で 1,349,859円です。毎日と連続の差は17円で、細かくしても増え方には上限があることが分かります。

倍になるまでの年数と72の法則

年利 r の複利で元本が2倍になる年数は ln 2 ÷ ln(1 + r) です。r が小さいと ln(1 + r) ≒ r なので、0.693 ÷ r、つまり「69.3 を利率(%)で割る」に近づきます。暗算しやすいように 72 で割るのが「72の法則」です。

年利 正確な年数 72÷利率 70÷利率 69.3÷利率
1%69.6672.0070.0069.30
3%23.4524.0023.3323.10
5%14.2114.4014.0013.86
7%10.2410.2910.009.90
10%7.277.207.006.93
20%3.803.603.503.46
50%1.711.441.401.39

69.3 は連続複利での正確な値(ln 2 × 100)ですが、年1回の複利では 72 のほうが 6〜10% の範囲でよく合いました。利率が 20% を超えると、どの近似もずれが大きくなります。

指数関数的な増え方・半減期と自然対数

この節では、「指数関数的に増える・減る」ものの時間を、自然対数で求める方法が分かります。

量が N(t) = N₀ × e の (k t) 乗 で変わるとき、ある倍率になるまでの時間は t = ln(倍率) ÷ k で求まります。自然対数は「指数の中の t を取り出す」道具です。

1

倍になる時間

ln 2 ÷ k。1日5%で増えるなら ln 2 ÷ ln 1.05 = 14.2 日。

連続なら ln 2 ÷ 0.05 = 13.9 日

2

10倍になる時間

ln 10 ÷ ln 1.05 = 47.2 日。2倍の約3.3倍の時間。

ln 10 ÷ ln 2 = 3.32

3

半減期

減る速さ k が 0.1155/時なら ln 2 ÷ 0.1155 = 6.0 時間。

6時間ごとに半分

4

速さ k を求める

2点の値から k = ln(N₂ ÷ N₁) ÷ (t₂ − t₁)。

対数をとると直線になる

半減期 6 時間の例で、100 から始めた量を計算すると、6時間後 50.01、12時間後 25.01、24時間後 6.25 でした。グラフの縦軸を対数にすると、このような指数関数の変化はまっすぐな線になります。ログの件数・ユーザー数・感染者数などの増え方が「指数関数的か」を確かめるときに、値の自然対数をとって直線に乗るかを見るのはこのためです。

リトライの待ち時間を 1秒・2秒・4秒…と倍にしていく「指数バックオフ」も、同じ指数関数の考え方です。関連記事「指数バックオフとは?リトライ間隔の決め方とジッターの実装」で扱っています。

機械学習の自然対数:対数損失・交差エントロピー・logsumexp

この節では、機械学習で自然対数がどこに使われ、どんな桁あふれ・桁落ちが起きるかが、実行結果で分かります。

分類モデルの評価に使う対数損失(log loss・交差エントロピー)は、正解に付けた確率 p の自然対数にマイナスを付けた −ln p の平均です。自信を持って外すほど、損失が急に大きくなります。

import math
from sklearn.metrics import log_loss
y = [1, 0, 1, 1]
p = [0.9, 0.2, 0.6, 0.99]
manual = -sum(math.log(pi) if yi else math.log(1-pi) for yi, pi in zip(y, p))/len(y)
print("manual log loss =", manual, " sklearn =", log_loss(y, p))
manual log loss = 0.21234500664788203  sklearn = 0.21234500664788206

手で自然対数を使って計算した値と、scikit-learn 1.9.1 の log_loss が最後の桁を除いて一致しました。scikit-learn の log_loss は自然対数を使っています。正解の確率 p ごとの損失は次のとおりです。

正解に付けた確率 p −ln p(ナット) −log₂ p(ビット)
0.990.01010.0145
0.90.10540.1520
0.50.69311.0000
0.12.30263.3219
0.014.60526.6439
0.0016.90789.9658
0(完全に外す)無限大(下限で切って 36.04)—

p = 0 のとき、Python の math は ValueError: math domain error、NumPy は inf と divide by zero encountered in log になりました。scikit-learn の log_loss は確率を倍精度の最小幅(2.22e-16)で切って計算するため 36.04365… を返します(−ln(2.22e-16) と同じ値)。自作の損失関数では、np.clip(p, 1e-15, 1 - 1e-15) のように下限を付けるのが定番です。

確率のかけ算は自然対数の足し算にする

product of 1000 probabilities 0.01
prod = 0.0  sum of log = -4605.17018598809

0.01 を1000回かけると 1e-2000 で、倍精度で表せる最小の数(約 1e-308)より小さいため 0.0 になりました(アンダーフロー)。自然対数をとって足すと −4605.17 で正しく扱えます。最尤推定で「尤度」ではなく「対数尤度」を最大化するのはこのためで、かけ算が足し算になり、微分もしやすくなります。

softmax のあふれと logsumexp

naive: [nan nan nan] ['overflow encountered in exp', 'overflow encountered in exp', 'invalid value encountered in divide']
shift max: [0.09003057 0.24472847 0.66524096]
scipy softmax: [0.09003057 0.24472847 0.66524096]
log(sum(exp(z))) naive = inf ['overflow encountered in exp']
logsumexp = 1002.4076059644444

z = [1000, 1001, 1002] の softmax を式どおり計算すると、e の 1000 乗があふれて nan になりました。いちばん大きい値を引いてから exp をとると、結果は変わらずにあふれを防げます。ln(Σ e の z 乗) も同じで、SciPy の logsumexp は 1002.4076 を正しく返しました。交差エントロピーの考え方は、関連記事「エントロピーとは|意味・計算・交差エントロピーをPythonで実演」、確率の分布の種類は関連記事「確率分布とは|種類一覧・平均と分散・選び方をPythonで実演」で扱っています。

1

0 を渡さない

確率の対数は、下限(1e-15 など)で切ってから計算する。ライブラリの損失関数は内部で切っていることが多い。

log loss

2

かけ算を足し算にする

確率や尤度をたくさんかけるときは、自然対数の和で持つ。最後に必要なら exp で戻す。

対数尤度

3

exp の前に最大値を引く

softmax・log(Σexp) は最大値を引いてから計算する。SciPy の softmax・logsumexp、PyTorch の log_softmax はこの処理を含む。

logsumexp

4

1 に近い確率は log1p

ln(1 − p) で p が小さいなら log1p(−p)。前の節の表のとおり、1e-12 より小さいと差がはっきり出る。

桁落ち

自然対数の判断表:どの関数を使うか

この節では、やりたい計算ごとに、どの対数関数を選べばよいかが一覧で分かります。

自然対数は log(SQL は ln)、底10と底2は専用の関数、0に近い x は log1p、が基本です。

やりたいこと 選ぶ関数 避ける書き方 理由(実測)
自然対数log(x)、SQL は ln(x)SQL の log(x)PostgreSQL・SQLite は底10
桁数を数えるlog10(x)log(x)/log(10)1000 で 2.9999999999999996
ビット数・二分探索の回数log2(x)、整数なら最上位ビットlog(x)/log(2)2 の 29 乗で 29.000000000000004
0に近い x の ln(1+x)log1p(x)log(1+x)x=1e-15 で11%ずれる
確率のかけ算ln の和そのままかけ算0.01 の1000乗が 0.0
softmax・log(Σexp)logsumexp・最大値を引くexp をそのままz=1000 で nan・inf
負の数の対数cmath.log・np.emath.logmath.logValueError になる
  • NumPy の配列は np.log・np.log10・np.log1p:math の関数は配列を受け取れません。配列の操作は、関連記事「NumPyの使い方 基本一覧|配列の作成・演算・形状変更」で扱っています。
  • 表示で丸められているだけの場合もある:PHP の echo や awk の printf は桁を省いて表示します。比べるときは桁数を指定して出力します。

よくある質問

Q. 自然対数とは何ですか? A. ネイピア数 e(約 2.71828)を底とする対数です。ln x は「e を何乗すると x になるか」を表し、e の x 乗(指数関数)の逆の計算です。ln 1 = 0、ln e = 1、ln 10 ≒ 2.302585 です。

Q. ln と log の違いは何ですか? A. ln は必ず自然対数です。log は底を省いた書き方で、数学やプログラミング言語では自然対数、関数電卓・工学の一部・PostgreSQL や SQLite では常用対数(底10)を指します。資料やツールごとに確かめるのが確実です。

Q. ln の読み方は? A. 「エルエヌ」と読むのが一般的で、「ログ」「ナチュラルログ」とも読みます。ラテン語の logarithmus naturalis の頭文字です。

Q. e はなぜ 2.718… なのですか? A. (1 + 1/n) の n 乗で n を大きくしていったときに近づく値が 2.718… だからです。年利100%の複利を細かくしていくと1年後に e 倍に近づく、と言い換えられます。階乗の逆数の和 1 + 1 + 1/2 + 1/6 + … でも同じ値になり、手元では18項で倍精度の限界まで合いました。

Q. 自然対数の「自然」とはどういう意味ですか? A. 微分すると 1/x、1/x の面積がそのまま自然対数、級数も簡単な形になるなど、数学の式が最も簡単になる底だからです。底10の常用対数は十進法という人間の都合で選ばれています。

Q. 自然対数を常用対数に変換するには? A. log₁₀ x = ln x × 0.434294、逆は ln x = log₁₀ x × 2.302585 です。プログラムでは割り算で変換すると最後の桁がずれることがあるため、log10 関数を使うのが正確です。

Q. ln 0 や ln(−1) はいくつですか? A. 実数の範囲では定義されません。x を 0 に近づけると ln x は −∞ に向かいます。プログラムでは Python が ValueError、JavaScript などが -Infinity や NaN、PostgreSQL がエラーを返しました。複素数まで広げると ln(−1) = πi です。

Q. Python で自然対数を計算するには? A. import math の後に math.log(x) です。配列なら numpy.log(x)、0に近い x の ln(1+x) は math.log1p(x) を使います。math.log(x, 10) は割り算で計算されるので、底10なら math.log10(x) を使います。

Q. log1p は何のためにあるのですか? A. ln(1 + x) を、x が 0 に近いときでも正確に計算するためです。log(1 + 1e-15) は 11% ずれ、log(1 + 1e-16) は 0 になりましたが、log1p は誤差 1e-16 程度でした。

Q. 機械学習ではなぜ自然対数を使うのですか? A. 確率のかけ算を足し算に変えてアンダーフローを防げること、微分が 1/x と簡単になること、exp(softmax・シグモイド)と打ち消し合うことが理由です。対数損失(log loss)も自然対数で計算します。

まとめ

  • 自然対数は底 e(2.718281828…)の対数で、ln x と書く。e の x 乗の逆の計算で、ln 1 = 0、ln e = 1、ln 10 = 2.302585。
  • e は (1 + 1/n) の n 乗の極限。倍精度では n = 1e16 で 1.0 になったが、log1p を使った式なら正しく近づく。
  • 多くの言語の log() は自然対数。PostgreSQL・SQLite の log() は底10なので、SQL では ln() を使う。
  • 底10・底2は log10・log2 を使う。割り算で変換すると log₁₀ 1000 が 2.9999999999999996 になった。
  • 0に近い x は log1p・expm1、確率は対数の和、softmax は最大値を引くか logsumexp で、桁落ち・桁あふれを防ぐ。

参考・出典

以下はいずれも 2026年10月29日 に確かめました。

  • Python「math — 数学関数」:https://docs.python.org/3/library/math.html
  • Python「cmath — 複素数のための数学関数」:https://docs.python.org/3/library/cmath.html
  • MDN「Math.log()」:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/log
  • Oracle「Math (Java SE 21 & JDK 21)」:https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Math.html
  • PostgreSQL 16「9.3. Mathematical Functions and Operators」:https://www.postgresql.org/docs/16/functions-math.html
  • SQLite「Built-In Mathematical SQL Functions」:https://sqlite.org/lang_mathfunc.html
  • MySQL 8.4 Reference Manual「Mathematical Functions」:https://dev.mysql.com/doc/refman/8.4/en/mathematical-functions.html
  • scikit-learn「sklearn.metrics.log_loss」:https://scikit-learn.org/stable/modules/generated/sklearn.metrics.log_loss.html
  • SciPy「scipy.special.logsumexp」:https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.logsumexp.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「自然対数とは?eとlnの意味・log1pが要る理由を8言語で実測」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ
参加受付中

AI駆動開発、 無料セミナー