この記事はtraP Advent Calendar 2023 14日目の記事です。
みなさん。大きい数と聞いて何を思い浮かべるでしょうか?
億?兆?京?無量大数?不可説不可説転?
Googleの名前の由来とも言われるグーゴル(googol)=やグーゴルプレックス(googleplex)=。
数学の証明に使用されたことのある最大の数である、グラハム数などを知っている人もいるかもしれません。
今回は、とにかく大きい数を作る芸術のような数学、巨大数という分野についての話です。
(巨大数wikiを大いに参考にさせて頂いております。)
注意:ここから話す"数"には制限をかけます。
具体的には、0を含む自然数(非負整数)とします。
以降、数、自然数と言ったら非負整数を指します。
つまり、小数や負の数、ましてや無限大という数は存在しません。(ややこしいのですが、別の数の定義として、自然数を含み、無限大のような数も許した順序数という数が出てきますが、あくまで別物と考えてください。)
何も考えずデカい数を作ってみる
まず、大きい数を普通に作ってみましょう。9をたくさん書けばいいのです。
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
これは、このように略記することができます。
また、このように近似できます。
ここで大きさに重要なのは、底(10にあたる部分)ではなく指数(100にあたる部分)です。
底を10倍することと、指数に1を足すことが等価なことからすぐにわかります。
なので、このデカイ数をそのまま指数にしてしまいましょう。
そして、これをたくさん書けばいいですね。
そして、このように略記することができます。
もうなんとなく分かりましたね。
この個数を、そのままこの数に置き換えてしまえばよいのです。
ここでこのような略記を導入します。
もちろんこの矢印は一番右から計算していきます。
そうすると、置き換えたものはこう書けます。
もうなぜ上のような書き方を定義したのかわかるはずです。
たくさん書いて、略記して、たくさん書いて、略記して、を繰り返します。
矢印を増やして定義していき、その矢印の個数をべき乗の形で書くイメージです。
具体的には以下のように定義します。
これも右から計算していきます。
もう感のいい人は気づいたかも知れませんね。
そう、この矢印の指数に大きい数を入れてしまいましょう。具体的には以下のように定義します。
そしてついにたどり着きました。
グラハム数はと定義されます。
そして気付くはずです。
グラハム数はまだ大きい数とは言えないことに。
(なぜ3なのかは、2にしてみて実際に計算すればなんとなくわかります。)
ちなみにこの上矢印の書き方は矢印表記や上矢印表記と呼ばれ、巨大数ではまだLv.1の小ささです。
小さいです。
大きい数が作れる本質を見極め、もっと大きくする
さて今までのことを整理して、この方法で大きい数が作れる本質は何かを考えてみましょう。
やったことは、①略記、②たくさん書くです。
ここでの例を考えると、②は関数の合成として見ることができます。
そして①は②での合成の回数を変数として、新たな関数を定義すること、として見ることができます。
これを踏まえると以下のような関数を定義できます。
この関数を矢印表記で近似してみると、
そして、グラハム数の定義に使った関数は、と近似できます。
実は、は任意の自然数mについてよりも強いので、グラハム数は大体の矢印表記で書かれた数より大きいです。
この"関数の強さ"についてもう少し詳しく解説、定義します。
この後に説明する、関数を強くする方法"対角化"は、巨大数でもかなり重要な概念、考え方です。
関数が強いとは?
もう少し分かりやすい例で考えてみます。
多項式関数と指数関数のどっちが大きい数を作れるかを考えます。
直感的には指数関数の方が強そうです。
もう少し具体的に言うと、十分大きい数を代入すれば指数関数の方が大きい数を作れます。
つまり、を定数とした時に、となるが存在し、以上の数でも成り立つという意味です。
これは確かに直感的にも論理的にも成り立ちます。
ここでは、これを関数の強さの定義とします。
ちゃんと書くと、ある2つの関数に対し、がより強いとは、が以上の数全てに対し成り立つ、と定義されます。(数学的に書くと、)
(関数の強さの定義は、じゃないの?と思ってる人へ)
関数の比較は、どのレベルで増加具合が違うかを設定しなければいけません。
ここでの定義では足し算を使用しています。
上の定義では掛け算を使用しています。
しかし、足し算・掛け算に執着する必要はなく、としてべき乗を基準にしてもよいわけです。
この時、任意の多項式関数は同じ強さになります。
結局とにかく大きい数が作れれば何でもよく、大半の関数の比較は後に出てくる順序数を使った急増加関数で行うので、この定義そのものに意味はあまりないと考えています。
強い関数の定義を見れば、明らかには任意の自然数についてより強いことがわかります。(この、定数を変数化する、決まっているものを変数にしてより強くすることを対角化と言ったり言わなかったりします。)
もう少しわかりやすく言うと、とでは、10000000より大きい数を代入すればの方が大きい数を作れるということです。(この大きさの違いは、とのように、圧倒的な違いを生み出すことを確認してください。)
もう慣れてきましたね。
このという関数を新たにと置き、同じように任意の添字について定義をすればより強い関数を作れます。
そしてと続けていく...?
違いますよね。
もちろん数字で置いて定義します。
イメージとしてはという風に定義します。
そしてより強い関数としてという関数があって、それをと置いて、より強い関数をと置いて...そろそろ分かってきたと思います。
添字の個数を変数にした関数はより強い関数になります。
しかし、このまま強くし続けても表記が汚くなってしまいそうです。
ここで、この添字に順序数という新しい数(自然数ではない)を使います。
この順序数という概念を使えば、思ってるよりもずっと大きな数を簡単に、しかもわかりやすく定義できます。
とりあえず、関数の添字(数列)で、関数の定義として使っている性質を列挙します。
- 最も小さい添字()が存在する (関数の実体を定義しているのはのみ)
- ある添字について、必ず次の添字(添字の一番右の数をしたもの)が存在する (これで関数の合成をしている)(使う添字より小さい添字に対して存在すれば実用上十分である)
- ある添字が何らかの添字の次にならない(添字の一番右の数が0である)場合、大きい数を使って、より小さい添字であってかつそれなりに大きい添字を作れる(から) (これで関数の対角化をしている)
- 1つ前の添字にする、または上の操作によって得られる添字にすることによって、添字を小さくし続けるという操作が有限で終わる(結局はをとてつもなく繰り返しているだけなので、いつかにたどり着かなければいけない)
あと副産物として、関数の強さの比較が添字の比較で決まります。
この上の4つを満たすものが、数列ではなく普通の数として定義できればいいですよね?
実はできるんです。
順序数は自然数の拡張として定義されます。
よって最も小さい添字は0です。(性質1はクリア)
ここで、全ての自然数より大きい数を考えます。
これをと置きます。
つまり以下が成り立ちます。
任意の自然数に対して
何かすごく関数の強さでやった対角化っぽいですよね?
実はこれは添字に対応します。
は前の順序数がなく、より小さいけどその中では大きい順序数(この場合そのままn)を作れるので性質3を満たし、nは有限であることから性質4も満たす。
また、のような順序数も考えられ、これは添字に対応することもすぐにわかります。
もちろん性質は全て満たしたままです。
また、は数列の極限のようにも見えますね。
よって以下のように用語を定義します。
ある広義単調増加順序数列(常により大きくなり続ける順序数の列)の極限(この数列に出てくるどの順序数よりも大きい順序数)であって最も小さいもの(前の順序数が存在しないもの)を極限順序数。
極限順序数を定義する広義単調増加順序数列を基本列とする。
この時、の基本列としても条件を満たしてしまいますが、今回はの1つに絞ります。
そして、性質3を使う順序数は定義より極限順序数に限り、極限順序数にはそれを定義する基本列が存在するので、基本列のn番目の順序数(0番目が最初)と定義する。
これを、極限順序数に対しとする。
以上を踏まえ、関数を以下のように定義する。
あとは基本列から極限順序数を定義していき、より大きい順序数を作っていくだけです。
(実際は足し算や掛け算の順番に決まりがあったり、掛け算にはの記号は使わなかったりするのですが、特に気にしないで計算ができればいいです。今回は、より小さい順序数を右側に置くようにしています。)
大体のイメージは以下のようになります。
もう少し正確に定義すると、以下のようにを定義します。(ワイナー階層という名前がついてます。)
実際に具体的に計算してみましょう。
もまた極限順序数になる場合もあります。
これを踏まえて数列の添字と順序数を対応させてみます。
そして、より、添字の個数を変数化した関数はと書けます。
実は、であらわされる関数はとてつもなく大きく、今後紹介するほぼ全ての関数がより小さい順序数を使って近似できます。
よってこの順序数を使った関数は急増加関数と呼ばれ、様々な関数を近似し、その強さを比べる指標としてよく使われます。(実際はでは足りず、もっと大きな順序数を定義してより強い関数まで近似できるようになっていますが、より定義が複雑で難しくなっていくのでここでは扱いません。)
イカれた巨大数たちを紹介するぜ!
ここでは別のアプローチによる関数や表記を、その関数や表記の大きさを近似する急増加関数の順序数と一緒に、その順序数の順番に紹介します。
関数名を押すと巨大数Wikiに飛ぶので、近似の詳細等が知りたい場合は是非訪れてみてください。
レベル :アッカーマン関数
競プロを嗜む人は、Union-Findの計算量として、この関数の逆関数を聞いたことがあるでしょう。
実は、この関数の定義は3種類もあります。
どれも強さは同じなのですが、今回は一番有名なロビンソンによる定義を使用します。
とりあえず定義は以下のようになります。
この関数を矢印表記で表すとこのようになります。
法則性を分かりやすくするために、ここでは矢印表記を以下のように拡張しています。(このようにしても矢印表記の法則が成り立つことを確認してください。)
そして一変数にしたという関数はで近似できることがわかります。
レベル :チェーン表記
定義は4つのルールで決まります。
- (としてもよい)
- (上と合わせて、最後から2つまでに1があったら短くできる、と解釈できる。)
この表記は意外と強く、グラハム数が成り立ち、でグラハム数を圧倒的に超えます。
そして、(個の)が成り立ちます。
レベル :多変数アッカーマン関数
急増加関数で添字の数列の個数を増やしたような拡張を、アッカーマン関数に対して適用したものです。
定義は以下のようになります。
イメージとしてはをとすると、以下のような形になるので分かりやすいかもしれません。
自分は、急増加関数の強さは合成回数の変数化にあって、合成元の関数に元の変数を代入する必要はなく、1を入れるだけで十分である。と理解しています。(実際に急増加関数による近似は一致する。)
そして、(個の1)となります。
レベル :配列表記(BEAF)
一見チェーン表記と似ているが、そこから生まれる数は大きさの格が違う。
以下定義です。
自分はこの定義を以下のように解釈しています。
- 基本の定義
- 最終出力のための定義
- 最終出力のために配列を短くするする定義
- 5,6を途中で止めるための定義
- 多変数アッカーマン関数の4番目と同じ目的
- 同上
イメージとしては以下のように数が増えていきます。(大きい数になったものをで表します。)
(6)
(6の繰り返し)
(5)
(6)
(6の繰り返し)
(5)
(以上の繰り返し)
(5)
(以上の繰り返し)
(そして最後の数が1になる)
(配列の長さが1縮む)
(以上の繰り返し)
(配列の長さが2になる)
(最終結果)
そして、(個の)となります。
(この配列表記は様々な方法でさらに拡張されて、より強い表記がたくさんあります。)
レベル :ヒドラ関数
少し違ったアプローチによる関数です。
ヒドラとは、ギリシャ神話に出てくる複数の首を持った蛇の怪物の名前です。
以下のような文字列と操作を考えます。
正しく括弧の対応が取れる、(
,)
のみからなる文字列をヒドラとする。((
と)
の数が同じものと考えればいいです。)
ヒドラ中に出てくる空の括弧()
を頭とする。
ある頭に対して、頭を直接囲む括弧がもし存在するなら、その括弧と内側を首と呼ぶ。
あるヒドラと数に対し、頭を切る()という操作を以下のように定義する。
- 頭を一つ選び、消す
- 首があれば、その首を個複製する
また、頭を切ってヒドラが無くなった時、ヒドラを倒したと呼ぶ。
例えば、()
,(())
,(()())
,(()(()(())((()))))
はヒドラです。
(
,)(
,(()
はヒドラではありません。
ヒドラの頭を赤色に、首を太字にするとこのようになります。
(()())
,(()(()()(())))
頭を切る操作の例を示します。
例1:の時、(()(()()))
(()(()))
(()(())(())(()))
例2:の時、()
(この時、ヒドラは倒されています。)
そして、あるヒドラに対して以下のような操作の繰り返しをヒドラゲームと呼びます。
- ターン数をとする
- 以降以下の操作を繰り返す
- 頭を一つ選び、頭を切る()
- ヒドラが倒されたら止める
- ターン数を一つ増やす
このヒドラゲームは、全てのヒドラに対して、どのように頭を選んだとしても、必ずゲームが終わることが証明されています。
そしてヒドラ関数は以下のようになります。
ヒドラ((...()...))
(n個の括弧)に対してヒドラゲームを行ったときにかかるターン数の最大値
,,を求めてみます。(最大になる選び方のみ示します。)
T=1 : ()
倒した
T=1 : (())
T=2 : ()()
T=3 : ()
倒した
T=1 : ((()))
T=2 : (()())
T=3 : (())(())(())
T=4 : (())(())()()()()
T=5 : (())(())()()()
T=6 : (())(())()()
T=7 : (())(())()
T=8 : (())(())
T=9 : (())()()()()()()()()()
T=10 : (())()()()()()()()()
T=11 : (())()()()()()()()
T=12 : (())()()()()()()
T=13 : (())()()()()()
T=14 : (())()()()()
T=15 : (())()()()
T=16 : (())()()
T=17 : (())()
T=18 : (())
T=19 : ()()()()()()()()()()()()()()()()()()()
T=20 : ()()()()()()()()()()()()()()()()()()
T=21 : ()()()()()()()()()()()()()()()()()
T=22 : ()()()()()()()()()()()()()()()()
T=23 : ()()()()()()()()()()()()()()()
T=24 : ()()()()()()()()()()()()()()
T=25 : ()()()()()()()()()()()()()
T=26 : ()()()()()()()()()()()()
T=27 : ()()()()()()()()()()()
T=28 : ()()()()()()()()()()
T=29 : ()()()()()()()()()
T=30 : ()()()()()()()()
T=31 : ()()()()()()()
T=32 : ()()()()()()
T=33 : ()()()()()
T=34 : ()()()()
T=35 : ()()()
T=36 : ()()
T=37 : ()
倒した
実は、はグラハム数を超える値になり、が成り立ちます。
そしてです。
このヒドラゲームを少し改変すると、後に紹介するTREE関数より強くなります。
レベル :原始数列システム
ついにプログラミング言語で定義された数が出てきます。
実際には、原始数列数と名付けられた数を出力する疑似BASICプログラムが公開され、そのアルゴリズムを関数として見た時の強さがです。
以下その疑似プログラムを示します。
main.basdim A(∞):B=9
for C=0 to 9
for D=0 to B
A(D)=D
next
for E=B to 0 step -1
B=B*B
for F=0 to E
if A(E-F)<A(E) or A(E)=0 then G=F:F=E
next
for H=1 to B*G
A(E)=A(E-G):E=E+1
next
next
next
print B
自分はC++erなので、C++で書いたものも置いておきます。
main.cpp#include <iostream>
int A[∞], B = 9, C, D, E, F, G, H;
int main(void) {
for (C = 0; C <= 9; C++) {
for (D = 0; D <= B; D++) A[D] = D;
for (E = B; E >= 0; E--) {
B*=B;
for (F = 0; F <= E; F++) {
if (A[E - F] < A[E] || A[E] == 0) {
G = F;
break;
}
}
for (H = 1; H <= B * G; H++) {
A[E] = A[E - G];
E++;
}
}
}
std::cout << B;
return 0;
}
原始数列システムを関数とします。
このとき、プログラムで出力される値はです。
の数学的な定義は以下のようになります。
数列と数に対し、整数を以下のように定める
- が空の数列の時、
- が空の数列でない時
の悪い部分(数列での一部)を以下のように定める- かつを満たすが存在するならば、
- 存在しないとき、
そして(個の)とする
そして、とする
例えば、となります。
をC++で定義すると以下のようになります。
primitive_sequence_function.cppint P(int n) {
int A[∞], B = n, C, D, E, F, G, H;
for (D = 0; D <= B; D++) A[D] = D;
for (E = B; E >= 0; E--) {
B*=B;
for (F = 0; F <= E; F++) {
if (A[E - F] < A[E] || A[E] == 0) {
G = F;
break;
}
}
for (H = 1; H <= B * G; H++) {
A[E] = A[E - G];
E++;
}
}
return B;
}
そしてとなり、原始数列数です。
この表記を改良したバシク行列システムは、対応する順序数がいまだに知られていないほど超強力な関数になります。
レベル :TREE関数
いきなり変な記号の羅列が出てきましたが、これはよりクソデカいよくわからん順序数を使って、難しい集合論を使って定義された関数に入れていい感じに基本列を作れる順序数にしたものと思ってくれればいいです。
この関数にはグラフ理論が使われており、グラフ理論をよく知らない、わからない人は、この動画でも見てなんとなく理解してください。
†グラフ理論何もわからん†の人も見ることをお勧めします。
以下定義です。
- の頂点数は以下である
- を満たす全てについて、がにinf保存かつラベル保存埋め込み可能でない
を満たすような根付きn-ラベル付き木の列()であって、最も長い列の長さをとする
これは本当に頭がおかしくなるくらいに増加して、(今まで紹介した関数で現実的に書ける数)になります。
レベル 計算不能Lv.1:ビジービーバー関数
ついにレベルが計算不能になりましたが、これ以降に紹介する関数は文字通り計算不可能な関数たちです。
この関数の発想は、今まで出てきた関数が有限の文字数でプログラミングできるなら、C++で文字以下で書かれたプログラムで出力できる最大の数、みたいな感じでプログラミング言語そのものを対角化してしまえばいいじゃない、という感じです。
まず計算可能とは何かを説明しますと、有限の文字数でちゃんとプログラミングできる、と考えてくれれば大体大丈夫です。(つまり、ビジービーバー関数は有限の文字数でちゃんとプログラミングできません。)
多少情報科学を知っている人用に向けて説明すると、有限状態チューリングマシンで有限のステップで停止して答えを出力可能、と同値です。
ビジービーバー関数の定義は、(全ての-状態 2-記号チューリングマシンについて、空のテープから始めて停止するまでにテープに書かれた1の数の最大値)です。
この関数がなぜ計算不可能で、今まで紹介したどの関数より強いのかの感覚を説明します。
プログラムには無限ループが存在します。
なので、どのようなプログラムでも、n文字以内で書かれたプログラム全てを有限の時間で列挙することはできても、実際にそのプログラムを実行したときにどんな値が出るかを有限の時間で確認できません。(無限ループするかどうかを有限の時間で判断できないという意味です。)
そして、チューリングマシンというのは、パソコンと同じ性能を持つ、簡単な数学的モデルと思ってください。
同じ性能であるとは、パソコンにできることとチューリングマシンにできることが同じ、互いにシミュレーション可能、という意味です。
つまりプログラムに無限ループが存在するように、チューリングマシンにも無限ループが存在して、その出力を有限の時間で確認できません。
なのでは有限の文字数でちゃんとプログラミングできない。
つまり計算不可能です。
また、チューリングマシンには状態数というものがあり、これはプログラミング言語の文字数に相当すると思ってください。
なので(=状態数)を十分に大きくすれば、有限の文字数で書かれたプログラムをシミュレーションできるので、今まで紹介したどの関数もシミュレーションできる。
つまりどの関数よりも強いことになります。
さてこの関数の強さはパソコンを使って有限の時間で計算できるありとあらゆる関数より強いことがわかりました。
しかし計算不能"Lv.1"です。
ではLv.2に行きましょう。(このLv.nは、あくまで強さの比較をわかりやすくるためのもので、一般的に計算不可能関数を比較する基準ではありません。)
レベル 計算不能Lv.2:クサイ関数
さて、今までの議論を理解していれば、Lv.2なんて存在しなさそうです。
なぜなら、パソコンはなんでもできるからです。
しかし、唯一言及した"出来ないこと"がありましたね。
それは"無限ループするかどうかを有限の時間で判断すること"でしたね?
しかし、あるプログラムに対して、無限ループするかしないかは決まっています。
なので、それをまるで神託のように教えてくれるプログラム、神託機械を考えます。
実際には、プログラムに対して、が無限ループするなら1を、しないなら0を返す関数のように定義します。
なぜLv.2なのかの詳しい説明は、クサイ関数の定義の後します。
クサイ関数には、チューリングマシンとは別の簡単な数学的モデルである、SKIコンビネータ計算が使われています。
これは異常なほど簡単なので、定義を紹介します。
コンビネータと呼ばれる3つの記号に対し、ベータ簡約を以下のように定義する((
,)
は式のまとまりを示すためのもので、式の文字数には数えない。後ろに書いてある式は、よく使う関数のような書き方をして可読性を高めたもの)
Ix
=x
(=)Kxy
=x
(=)Sxyz
=xz(yz)
(=)
一番左のコンビネータを使ってベータ簡約することを出来なくなるまで繰り返して、最終的に得られる式を出力結果、出力結果に含まれる文字数を出力サイズとする(ベータ簡約が終わらない場合、出力結果も出力サイズも存在しない)
以下SKIコンビネータ計算の例を置いておきます。
Kあいう
===あう
Sabc
===ac(bc)
S(かっこ)い(いね)
===
(かっこ)(いね)い(いね)
=
かっこ(いね)い(いね)
SKS(KIS)
K(KIS)(S(KIS))
(KIS)
KIS
I
このSKIコンビネータ計算は、こんな見た目をしていますが、チューリングマシンをシミュレーションできます。
なので同じように無限ループするSKIコンビネータ計算が存在します。
SII(SII)
=I(SII)(I(SII))
=
SII(I(SII))
=I(I(SII))(I(I(SII)))
=I(SII)(I(I(SII)))
=
SII(I(I(SII)))
...
そしてこのSKIコンビネータ計算に、神託機械に相当する神託コンビネータΩ
を追加します。
Ωxyz
=x
の最終的な出力結果が存在してI
であるならy
、そうでないならz
計算例は以下のようになります。
Ω(KIS)SK
=S
(KIS
=I
)
Ω(SII(SII))SI
=I
(SII(SII)
は無限ループする)
Ω(Ω(SII(SII))SI)(KI)I
=KI
(Ω(SII(SII))SI
の出力結果は上の計算よりI
になる)
実はこのΩ
はとても厄介な性質を持っていて、Ω
の引数x
の中にΩ
を含む式を入れると、この式が無限ループするなら式を出力し、何らかの式を出力するなら無限ループする、という関数が作れてしまいます。
もう少し分かりやすい言い方をすると、"この文は間違っている"みたいなものが作れます。
これは矛盾が生じるので、そのような式は出力結果が存在しないとして、無視されます。
そしてクサイ関数は、S
,K
,I
,Ω
の4種類の文字からなる文字の式の出力サイズの最大値と定義されます。
までの、出力サイズが最大になる最初の式を置いておきます。
: S
: S(S)
: S(SS)
: S(SSS)
: SSS(SI)
: SSS(SI)S
: SSS(SI)SΩ
さて、この関数がなぜLv.2、ビジービーバー関数より大きいのか。
それは簡単です。
神託コンビネータΩ
の存在です。
このΩ
は、無限ループするかどうかをすぐに教えてくれます。
なので、有限の文字数と有限の時間でビジービーバー関数をシミュレーションできます。
そして、逆にビジービーバー関数で使ったチューリングマシンでは、Ω
を有限の時間でシミュレーションできません。
なので関数の強さが比較でき、こちらの方が大きい言えます。
つまり、Ω
がないただのSKIコンビネータ計算だと関数の強さは同じになります。
さて、まだまだ続きます。
次はL.3?です。
レベル 計算不能Lv.3?:ラヨ関数
Lv.3の後ろに?がついていますが、今から説明する関数の定義は、厳密に考えると問題があります。
ぜひ数学オタクの人は、自分でいろいろ調べてみて、どこが問題なのか考えてみてください。
では定義です。
(一階の集合論(一階述語論理)の言葉で個以内の記号で表現できるいかなる有限の正の整数よりも大きな最小の正の整数)
そしてラヨ数をとする。
もういろいろひどい定義ですね。
最初から一階述語論理とかなんとか、一体何を言っているのかわかりませんよね?
ざっくり説明すると、一階述語論理とは数学のほぼすべてを表現できる数学の言語、と考えて下さい。
つまり、この関数はほぼすべての数学を対角化しています!
もうなんだかすごいですよね!
もうここら辺まで来ると、詳細を書いても誰も読まなくなるので、さっさと次の関数に行って終わらせちゃいましょう。(別に自分が分かってないって意味じゃないからね!)
レベル 計算不能Lv.4:巨大数庭園数
これは、ニンゲンジャナイP進大好きbot様によって定義された数です。
関数には名前がついていないので、数の名前の略称を載せました。
えっ?本当の名前はなんだって?
ヤツの本当の名は...
「さあ盟友、ついに巨大数庭園の完成だ! この庭園の機能を説明しよう。まず1つ目は住所と間取り図の判定機能。文字列を読み込むと、それがどの箱庭の住所を表しているかやどの箱庭で再現可能な巨大数庭園の間取り図なのかを自動で判定してくれるんだ。次に2つ目が間取り図の解析機能。箱庭の住所を指定してそこで再現可能な巨大数庭園の間取り図を読み込むと、その庭園が生み出せる巨大数を教えてくれるのさ。そして肝心の3つ目の機能が巨大数の生成機能。ひとたび自然数を入力すると、それを文字数の上限とした範囲内にある全文字列を探索し、それぞれを住所と間取り図の判定機能に読み込ませることで箱庭ごとに再現可能な間取り図のみを残して列挙し、更に間取り図の解析機能に読み込ませることでそれらが生み出せる巨大数を入手し、それら全てをまとめ上げることで新たな巨大数を生み出せるんだ! え? それで本当に巨大な数が得られるのかって? 相変わらず盟友は疑り深いなあ。でもいいさ、この巨大数庭園自体の間取り図がここにある。これを解析機能に読み込ませれば、どれほど巨大な数を生み出せるのかを教えてくれるからね。え? この間取り図の文字数? そんなものを知って何になるんだい?」
だっ...!!
長い!!
この関数は一体何をやっているのかを、読んでくれそうなくらい簡単に説明すると、ラヨ関数では一階述語論理という数学の言語を使ったけど、これで表現できるのは"ほぼ"すべての数学なら、もっといろいろ表現できる言語を作って、それそのものも対角化して、それを何回か繰り返してしまおう!...みたいな感じ...のハズデス。ハイ。
実は自分もよくわかってません。
しかし、この巨大数庭園数は、世界中の人がいる巨大数界隈で、今のところ最も大きい数として認識されています。
そう!実質的に世界で一番デカい数が!日本の!しかもタラーが!作ったのです!
なんかいいですねぇ..
以上で巨大数の話を終わります。
ちゃんと最後まで読んだあなたはきっと数学オタクです。
明日のアドベントカレンダーは@comaviusが担当します!お楽しみに!