正∞角形と円

一般に、正n角形の各頂点は円周上の θ = 2π * k/n (0≦k<n) の点として表せます。
逆に単位円上の点を列挙しようと思ったら、上の式で n→∞ としてやればよさそうです。

Haskell で書くとこんなかんじ。zeroToOne は区間[0,1)の全ての有理数を列挙する無限リストです。

import Data.Ratio
zeroToOne = 0 : [ b % a | a <- [1..], b <- [1..(a-1)], gcd a b == 1 ]
onCircle = [ (cos t, sin t) | x <- zeroToOne, let t = 2*pi * fromRational x ]

これにてめでたしめでたし、…とはいきません。

これでは円周上の全ての点をきちんと列挙できないのです。

それは何故か。

浮動小数点数 ≠ 実数だからとかいう話ではありません。
答えは、円周上の点なんてのは実数の濃度なので非可算な集合であり、そもそもリストとして列挙できるようなものではないから。
その意味で、例えば sinθ=0 を満たすθを列挙せよという問題とは本質的に異なります。

無限リストや無限ループで記述できるのはあくまで可算無限の集合だけです。定義を考えれば当たり前ですね。

つまり上記のプログラムで列挙されるのは正∞角形の全ての頂点ではありますが、円周上の全ての点ではありません。こいつらはもう全ッ然別物になっちゃいます。ポイントは円周上の点の中に (有理数 * π) で表せない角度が存在することです。

実数列挙の不可能性というのは、データ的に実数を表現できないことでも、計算量的にどうこうでもなく、そもそもそのような操作自体がうまく記述できない点にあります。
こういう基本的なことは、普段忘れがちだけど大事なことだよなーと思いました。



ところで、正n角形は n→∞ で円になります

ほら、Wikipedia にも「正∞角形を円とする」って書いてある。
あれ? と思うかもしれませんが、よくよく考えれば別に何もおかしなことはないですよ。

というわけでこの議論のどこが引っかかりやすいところなのか、ぜひ考えてみてください。


ヒント: 正∞角形の"頂点の"集合(可算) ⊂ 正∞角形の辺上の点の集合 = 円周上の点の集合