JavaScriptで円周率を求めてみる — 台形則だけで「3.14〜3.15」に収める
数学が好きなので、簡単な数学をプログラミングで再現してみたくなった。
題材はやっぱり 円周率($\pi$)。テーマとして分かりやすく、結果も実感しやすい。
なるべくラクをしたいので、ブラウザだけで動く JavaScript で十分。
追記:よくある質問
目次
- ゴールと方針
- なぜ JavaScript?
- 上半円の式の根拠
- 数式から実装へ(台形則)
- 実装コード(コピペでOK)
- 実行例:目標レンジを満たす
- プログラミングで数学をやると面白い理由
- 落とし穴とミニTIPS
- まとめと次の一歩
ゴールと方針
- ゴール:プログラムで $3.14 < \pi < 3.15$ を確認する
- 方針:半径 1 の円の面積を数値積分で近似し、$\pi$ を推定する
上半円は $y=\sqrt{1-x^2}$($-1 \le x \le 1$)で表せます。
この記事では 第1象限の $1/4$ 円だけ $x\in[0,1]$ を積分し、最後に 4倍 して全体面積に戻します:
$$
\text{Area} =\ 4 \int_{0}^{1} \sqrt{1 - x^2}\ dx
$$
なぜ JavaScript?
- 環境構築がいらない:ブラウザの DevTools コンソールで即実行
- 共有しやすい:URL + スニペット で説明できる
- 十分な速度:この規模の数値積分なら JS で困らない
上半円の式の根拠
1) 円の方程式からの導出
原点中心・半径 1 の円は「原点からの距離が 1 の点の集合」なので,
$$
\sqrt{x^2 + y^2} = 1 \Longleftrightarrow\ x^2 + y^2 = 1
$$
$y$ について解くと
$$
y = \pm \sqrt{1 - x^2}
$$
上半円($y\ge 0$)ではプラスを取り,
$$
\boxed{y=\sqrt{1-x^2}}\qquad(-1\le x\le 1)
$$
この記事では計算を簡単にするため $x\in[0,1]$ の第1象限のみを積分し,最後に 4倍 します。
2) 三角関数から見ても同じ
単位円上の点は $(x, y) = (\cos\theta, \sin\theta)$。
恒等式 $\sin^2\theta + \cos^2\theta = 1$ より
$$
\sin\theta = \pm\sqrt{1-\cos^2\theta}
$$
上半円($\sin\theta\ge 0$)を選べば,$x=\cos\theta$ なので $y=\sqrt{1-x^2}$($x\in[-1,1]$)。
3) 補足(関数として扱えるのは半分ずつ)
円全体は縦線テストに落ちるため $y=f(x)$ の関数にはできません。
ただし上半円は $y=\sqrt{1-x^2}$,下半円は $y=-\sqrt{1-x^2}$ として関数扱いでき,面積計算に十分です。
数式から実装へ(台形則)
区間 $[a,b]$ を幅 $h$ で $n$ 等分し,
$$
\int_a^b f(x)dx
\approx
h\left(\tfrac12 f(x_0) + \sum_{k=1}^{n-1} f(x_k) + \tfrac12 f(x_n)\right)
\qquad
x_k = a + kh,\ h=\frac{b-a}{n}.
$$
今回の設定:
- $f(x)=\sqrt{1-x^2}$
- $[a,b]=[0,1]$(第1象限)
- 最後に 4 倍 すれば円全体の面積に一致
補足:$f(x)=\sqrt{1-x^2}$ は
$$
f''(x)= -(1-x^2)^{-\tfrac{3}{2}} <0\quad(|x|<1)
$$
と 下に凸 なので,台形則の近似は常に少し小さめに出ます。
分割数 $n$ を増やすと,下から $\pi$ に単調収束します。
実装コード(コピペでOK)
ブラウザのコンソール or Node.js でそのまま実行できます。
// f(x) = sqrt(1 - x^2) を 0..1 で台形則近似し、円の面積(=4倍)を返す
function estimatePiByTrapezoid(n = 100) {
const dx = 1 / n;
// 端点は 1/2 の重み
let sum = 0.5 * Math.sqrt(1 - 0 * 0) + 0.5 * Math.sqrt(1 - 1 * 1);
for (let k = 1; k < n; k++) {
const x = k * dx;
sum += Math.sqrt(1 - x * x);
}
return 4 * sum * dx;
}
// 目標レンジ(3.14〜3.15)に入るまで n を倍々に増やす簡易ループ
function estimatePiInRange(low = 3.14, high = 3.15) {
let n = 10;
let pi = estimatePiByTrapezoid(n);
while (!(pi > low && pi < high)) {
n *= 2; // ざっくり倍々で近づける
if (n > 1_000_000) break; // セーフティ
pi = estimatePiByTrapezoid(n);
}
return { pi, nUsed: n };
}
// 実行例(結果は環境で多少異なります)
const { pi, nUsed } = estimatePiInRange(3.14, 3.15);
console.log(`π ≈ ${pi}(n=${nUsed} 分割, 台形則)`);
実行例:目標レンジを満たす
参考値(台形則):
- $n=50 \Rightarrow 3.138268\ldots$(まだ $3.14$ に届かない)
- $n=100 \Rightarrow 3.140417\ldots$($3.14 < \pi < 3.15$ を満たす)
- $n=200 \Rightarrow 3.141176\ldots$
- $n=1000 \Rightarrow 3.141555\ldots$
$n\approx 100$ 以上で,今回の目標レンジを満たせます。
(台形則の計算量は $O(n)$。目的次第で $n$ を増やすか,より高精度な公式に切り替えるかを選びます。)
プログラミングで数学をやると面白い理由
式が「静止画」から「動画」になるからです。
パラメータを動かす $\rightarrow$ 結果が揺れる $\rightarrow$ 観察して仮説 $\rightarrow$ さらに動かす。
この小さなループが,数学を体験型に変えてくれます。
1) 「式」が「手触り」に変わる
- 分割数 $n$ を増やすと値が 下から $\pi$ に近づく(今回は下に凸 $\Rightarrow$ 台形則は過小評価)。
- $n$ を倍にするたび,誤差が一定比率で小さくなる傾向を “目で” 追える。
数式を覚えるだけでは得にくい 感覚 が残ります。
2) 誤差と収束を“観察ゲーム”にする
台形則の誤差はなめらかな関数に対して概ね $O(1/n^2)$。
$n$ を2倍にすると誤差はおよそ $1/4$。予想と観測が噛み合うと,とても気持ちいい。
// 収束の様子を簡単観測(検証のため Math.PI 参照)
function observeConvergence(ns = [50, 100, 200, 400, 800]) {
const rows = [];
let prevErr = null;
for (const n of ns) {
const approx = estimatePiByTrapezoid(n);
const err = Math.abs(approx - Math.PI);
rows.push({ n, approx, err, errRatioToPrev: prevErr ? err / prevErr : null });
prevErr = err;
}
console.table(rows);
}
// observeConvergence();
3) 設計そのものが数学になる
- 端点の重み($1/2, \dots, 1/2$)をどう扱うか
- 方法の選択(台形則 / 中点則 / Simpson / 自適応)
-
計算量と精度のトレードオフ
これらはソフトウェア設計の思考と重なります。良い近似 = 良い設計。
4) 実験の“型”があると学びが速い
- 目的(今回なら「$3.14\text{〜}3.15$ に入るか」)
- 操作変数($n$)
- 指標(近似値・実行時間・※検証時のみ誤差)
- 記録(
console.table)
これだけで,小さな研究になります。
5) 可視化で理解が跳ねる
Canvas で半円と台形を描く,誤差を簡易バーで出す等,見える化は理解を加速します。
落とし穴とミニTIPS
- ラジアン/度の混同:角度を扱う場合は必ずラジアン。
- 端点の重み忘れ:台形則の端は $1/2$。抜けると地味にズレます。
- $n$ を増やしすぎ問題:浮動小数点の丸め誤差・時間コスト。方法を変える選択肢も。
- 停止条件の設計:レンジ到達・誤差の相対変化・最大反復回数などの複合条件が安全。
まとめと次の一歩
- JSだけでOK:ブラウザのコンソールですぐ試せる
- 台形則で $4\int_0^1 \sqrt{1-x^2}dx$ を近似し,$3.14 < \pi < 3.15$ を確認できた
- プログラミング×数学は楽しい:式が体験になり,設計思考と一体で学べる
次の一歩:
- 同じ $n$ でもっと高精度な Simpson 則へ
- 曲率に応じて分割を変える 自適応積分
- 乱数で面積比から近似する モンテカルロ法(シード固定で再現性◎)
ハマってきた人は、競技プログラミングの世界も楽しいかも!