素数の個数を求める式
かなり昔から、ある数nより小さい素数の個数$p$は、次の簡単な式で近似できることが知られていた。
素数と自然対数には深い関係があるらしい。それは何か。素数は無限にあるけれどこの関係はどこまでも続くのか。当時の学者もそう思って研究したようだが、なかなか解決できなかった。その中、1859年に数学者リーマンが次の式を発見した。
$\pi(x)$は素数の個数を表す関数で、どんな大きな$x$に対しても$x$より小さい素数の個数が得られる。見れば見るほど不思議な式だ。$x$は自然数ではなくて実数、右辺には$n$乗根もあるのに、和は素数の個数という自然数に収束するというのだから。$\mu(n)$はメビウス関数という変な関数。$n$がどのような素数の積かによって$-1,0,1$のどれかの値になる。$J(x)$は、次のように定義されてる。
$Li(x)$や$\rho$など見慣れない記号があるが、調べてみると電卓でも計算できそう。2番めの項の$\rho$が複素数なので、複素数の関数計算ができる電卓が必要だ。式の詳細は理解できないから計算のための情報は書籍やネット頼み。途中が怪しくても、それなりの計算結果が得られればよし、としよう。
なぜ電卓?
実際に素数の個数を知ることは簡単だ。https://ja.wolframalpha.com/へ行って、$PrimePi(1000,000)$と入力すれば100万以下の素数が78498個あることがすぐに分かる。今回の興味は、今も数学者を悩ます歴史的な数式を電卓で計算する、ということにある。上の式の複素数$\rho$は、計算機の父チューリングも計算したとのこと。複素数で$\log(x)$や$e^x$の計算ができるHP35sを購入したので、摩訶不思議な数式を電卓で計算できたら面白い!というノリだ。電卓の複素数計算自体が面白くて、例えば虚数単位$i$の$i$乗を計算したのが右の写真。
これは実数しかも超越数。
近似計算
$J(x)$の計算がプログラムの中心。第2項の$\rho$は無限個あることが証明されているから、加算も無限回でスパコンでも完全な計算はできない。それに電卓の計算速度は極端に遅いから、実際に加算できるのは10項以下だろう。正確な値を求めるプログラムにはならないが、そこは気楽な素人の遊びということで。
第1項 $Li(x)$
この項はネットで見つけた計算式で求めた。$\log$は自然対数なので電卓ではLNだ。この項は複素数ではないので普通の電卓でも計算できる。
正しい値と比べてみると$x$の値に対して必要な精度が得られる項数$n$が異なる。プログラムでは必要な精度が得られるように$x$の値から$n$を適当に計算した。
第2項 $\sum Li(x^\rho)$
この項の計算が今回の中心だ。$\rho$はリーマンの論文に出てくるゼータ関数 $\zeta(s)$とやらがゼロとなる値で複素数。
$\rho$の計算は大変複雑らしいが、先程のhttps://ja.wolframalpha.com/でN[ZetaZero[1],20]と入力すれば、1番目の$\rho_1$が20桁まで計算できる(感謝)。
このサイトでプログラムに使う$\rho_1\sim\rho_8$を計算した。
第1項と似たような計算式だが、$\rho$が複素数なので35sの出番。調べた$\rho_1\sim\rho_8$の複素数値をそのまま使って関数計算する。$Ei(z)$の近似値を求める和は、実部はかなり正確だったが虚部は誤差が大きくなった。でも最終的な計算では実部の値しか使わないので助かった。リーマン先生は、全ての$\rho_n$の実部は$\frac{1}{2}$である、と予想したが、論文発表から160年が経過する現在でも証明されていない。証明に100万ドルの懸賞金がかかっている。
第3,4項
この2項は大きな値にならないとのことなので省略した。35sには数値積分の機能があるけれど時間がかかりすぎて使えそうにない。
プログラム
複雑な計算なので、プログラムは複数の部分に分けた。HP35sを持っていないと意味はないが、記録のために記載。こうして記載してみるとそれほど長いプログラムではない印象。
- $Ei(z)$の計算
- $Li(x)$の計算
- $J(x)$の計算
$\rho=\frac{1}{2}+it$は、最初の8個をメモリに入れ実行時に参照した。
- $\pi(x)$の計算
メビウス関数$\mu(n)$は事前に計算した値をメモリに入れ実行時に参照。調べると$\pi(10^{12})$まで計算するには$\mu(40)$程度までの値が必要と思われたが、P026の短縮により実際の計算は$\mu(10)$程度で終了する。
計算結果
プログラムの実行結果は次のとおり。肝心の$\rho$についての和は8項にすぎないが、$\rho$を使わない計算と比べると計算精度が改善されている。下表のように加算する項数が0($\rho$を使わない),5,8と増えると誤差は減少する。10億未満の素数の個数は5000万個以上あるが、それが9個の誤差で得られているのはいい感じだ。
表末尾の$x=10^{12}$(10兆)では誤差の大小が逆転する。近似式の問題だろうか、それとも35sの有効桁数に近づいて計算誤差が累積しただろうか。計算時間は8項加算の時間だが、直線的に増えないのは、前述の$\mu(n)$関数の値によって計算量が不連続に変化することが影響していると思われる。途中経過の表示をやめると計算時間を5~10秒短縮できる。
印象と課題
HP35sのプログラム言語は、キーボードマクロに最小限の制御命令が追加されたコンパクトな仕様だが、メモリ参照命令が効果的で、素直に計算式をプログラム化できたことに感心した。計算速度もまあまあだ。課題は計算精度。近似式の検討、計算時間短縮のために省略した項や和の打ち切りなどを上手に処理できれば精度の向上が期待できる。次の機会に考えてみよう(いつになるやら)。
感想
素数の個数が実数や複素数の関数計算で求められることは、やはり不思議な感じがする。150年以上数学者の挑戦を跳ね返し続けているリーマン予想、そのややこしい式が手のひらで計算できるのを見たら、リーマン先生も面白がってくれるだろう。