正∞角形と円
一般に、正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 にも「正∞角形を円とする」って書いてある。
あれ? と思うかもしれませんが、よくよく考えれば別に何もおかしなことはないですよ。
というわけでこの議論のどこが引っかかりやすいところなのか、ぜひ考えてみてください。
ヒント: 正∞角形の"頂点の"集合(可算) ⊂ 正∞角形の辺上の点の集合 = 円周上の点の集合