電卓でリーマンの素数個数関数を計算した

素数の個数を求める式

かなり昔から、ある数nより小さい素数の個数$p$は、次の簡単な式で近似できることが知られていた。

$$p\sim\frac{n}{log(n)}$$

素数と自然対数には深い関係があるらしい。それは何か。素数は無限にあるけれどこの関係はどこまでも続くのか。当時の学者もそう思って研究したようだが、なかなか解決できなかった。その中、1859年に数学者リーマンが次の式を発見した。

$$\pi(x)=\sum_{n=1}\frac{\mu(n)}{n}J(\sqrt[n]{x}) ただし \sqrt[n+1]{x}<2 まで$$

$\pi(x)$は素数の個数を表す関数で、どんな大きな$x$に対しても$x$より小さい素数の個数が得られる。見れば見るほど不思議な式だ。$x$は自然数ではなくて実数、右辺には$n$乗根もあるのに、和は素数の個数という自然数に収束するというのだから。$\mu(n)$はメビウス関数という変な関数。$n$がどのような素数の積かによって$-1,0,1$のどれかの値になる。$J(x)$は、次のように定義されてる。

$$J(x)=Li(x)-\sum_{\rho}(Li(x^\rho)+Li(x^{1-\rho}))-\log2+\int_x^\infty\frac{dt}{t(t^2-1)\log t}$$

$Li(x)$や$\rho$など見慣れない記号があるが、調べてみると電卓でも計算できそう。2番めの項の$\rho$が複素数なので、複素数の関数計算ができる電卓が必要だ。式の詳細は理解できないから計算のための情報は書籍やネット頼み。途中が怪しくても、それなりの計算結果が得られればよし、としよう。

なぜ電卓?

実際に素数の個数を知ることは簡単だ。https://ja.wolframalpha.com/へ行って、$PrimePi(1000,000)$と入力すれば100万以下の素数が78498個あることがすぐに分かる。今回の興味は、今も数学者を悩ます歴史的な数式を電卓で計算する、ということにある。上の式の複素数$\rho$は、計算機の父チューリングも計算したとのこと。複素数で$\log(x)$や$e^x$の計算ができるHP35sを購入したので、摩訶不思議な数式を電卓で計算できたら面白い!というノリだ。電卓の複素数計算自体が面白くて、例えば虚数単位$i$の$i$乗を計算したのが右の写真。

$$i^i=e^{-\frac{\pi}{2}}\sim0.2078795763507619085469...$$

これは実数しかも超越数。

近似計算

$J(x)$の計算がプログラムの中心。第2項の$\rho$は無限個あることが証明されているから、加算も無限回でスパコンでも完全な計算はできない。それに電卓の計算速度は極端に遅いから、実際に加算できるのは10項以下だろう。正確な値を求めるプログラムにはならないが、そこは気楽な素人の遊びということで。

第1項 $Li(x)$

この項はネットで見つけた計算式で求めた。$\log$は自然対数なので電卓ではLNだ。この項は複素数ではないので普通の電卓でも計算できる。

$$Li(x)=\frac{x}{\log x}\sum_{k=0}^n\frac{k!}{\log(x^k)}$$

正しい値と比べてみると$x$の値に対して必要な精度が得られる項数$n$が異なる。プログラムでは必要な精度が得られるように$x$の値から$n$を適当に計算した。

第2項 $\sum Li(x^\rho)$

この項の計算が今回の中心だ。$\rho$はリーマンの論文に出てくるゼータ関数 $\zeta(s)$とやらがゼロとなる値で複素数。

$$\rho=\frac{1}{2}+i t ただし \zeta(\rho)=0$$

$\rho$の計算は大変複雑らしいが、先程のhttps://ja.wolframalpha.com/でN[ZetaZero[1],20]と入力すれば、1番目の$\rho_1$が20桁まで計算できる(感謝)。

$\rho_1=0.50000000000000000000 + 14.134725141734693791 i$

このサイトでプログラムに使う$\rho_1\sim\rho_8$を計算した。

$$Li(x^\rho)=Ei(\rho\log x)$$
$$Ei(z)=\frac{e^z}{z}\sum_{k=0}^n\frac{k!}{z^k}$$

第1項と似たような計算式だが、$\rho$が複素数なので35sの出番。調べた$\rho_1\sim\rho_8$の複素数値をそのまま使って関数計算する。$Ei(z)$の近似値を求める和は、実部はかなり正確だったが虚部は誤差が大きくなった。でも最終的な計算では実部の値しか使わないので助かった。リーマン先生は、全ての$\rho_n$の実部は$\frac{1}{2}$である、と予想したが、論文発表から160年が経過する現在でも証明されていない。証明に100万ドルの懸賞金がかかっている。

第3,4項

この2項は大きな値にならないとのことなので省略した。35sには数値積分の機能があるけれど時間がかかりすぎて使えそうにない。

プログラム

複雑な計算なので、プログラムは複数の部分に分けた。HP35sを持っていないと意味はないが、記録のために記載。こうして記載してみるとそれほど長いプログラムではない印象。

  • $Ei(z)$の計算
E001LBL E
E0021
E003XEQ E009E009以下をサブプログラムとして実行
E004RCL÷ Z
E005RCL Z
E006$e^x$
E007×
E008RTN
E009STO O
E010R↓
E011STO Z
E0121
E013STO S
E014STO K
E015RCL÷ Z
E016RCL× K
E017STO+ S
E018ISG K
E019ENTER
E020DSE O
E021GTO E015
E022RCL S
E023RTN
  • $Li(x)$の計算
L001LBL L
L002STO Y
L003LN
L004ENTER
L005IP
L0061
L007-
L008XEQ E009
L009RCL× Y
L010RCL Y
L011LN
L012÷
L013RTN
  • $J(x)$の計算
第2項の$\rho$による和は計算時間を勘案して8項までとした。

$\rho=\frac{1}{2}+it$は、最初の8個をメモリに入れ実行時に参照した。

$t=\{14.1347251417,\;21.0220396388,\;25.0108575801,\;\cdots\}$だ。
HP35sでは、$\rho_1$を $0.5\;i\;14.1347251417$ と入力する。

J001LBL J
J002LN
J003STO X変数Xに$\log{x}$を入れておく
J004LASTx
J005XEQ L001$Li(x)$を計算
J006STO QメモリQに格納
J0070$\sum_{\rho} Li(x^\rho)$計算開始
J008STO T和を入れる変数Tをクリア
J00930.037メモリの30〜37番地に$\rho$の値が8個格納されている
J010STO Iループカウンタを初期化
J011RCL(I)$\rho$(複素数)をメモリから得る
J012RCL× X$\rho\log{x}$を計算
J013XEQ E001$Li(x^\rho)$を$Ei(\rho\log{x})$で計算
J014STO+ T結果をTに加算
J015ISG Iループ終了を検査
J016GTO J008
J017RCL Q$Li(x)$を呼び出す
J018RCL T$\sum(Li(x^\rho)+Li(x^{1-\rho}))=2Re(\sum Li(x^\rho))$
J0192虚部が相殺されるので和は実部の2倍
J020×
J021ENTER
J022ABS実部を計算(35sには実部を得る機能がない)
J023x<>y$Re(z)=|z|\cos(\arg(z))$
J024ARG
J025COS
J026×
J027-$J(x)=Li(x)-\sum_{\rho}Li(x^\rho)$が得られる
J028RTN
  • $\pi(x)$の計算

メビウス関数$\mu(n)$は事前に計算した値をメモリに入れ実行時に参照。調べると$\pi(10^{12})$まで計算するには$\mu(40)$程度までの値が必要と思われたが、P026の短縮により実際の計算は$\mu(10)$程度で終了する。


P001LBL P
P002STO P
P0030
P004STO W
P005STO Vここまでは内部変数等の初期化
P00640メモリの40番地から$\mu(n)$の値が格納されている
P007STO J
P0081$\pi(x)$計算のループ先頭
P009STO+ V
P010STO+ J
P011RCL(J)$\mu(n)$を得る
P012x=0?
P013GTO P009$\mu(n)=0$なら$J(x)$は計算不要
P0142
P015RCL P
P016RCL V
P017PSE途中経過を表示するため1秒停止
P018$\sqrt[x]{y}$$\sqrt[n]{x}$
P019$x\le y$?$\sqrt[n]{x}<2$なら計算終了
P020GTO P030
P021XEQ J001$J(\sqrt[n]{x})$を計算
P022RCL÷ V$/n$
P023RCL×(J)$\frac{\mu(n)}{n}$
P024STO+ WW $=\sum \frac{\mu(n)}{n}J(\sqrt[n]{x})$
P025ABS
P0261.0計算時間短縮のため 項<1 なら計算中止
P027x<y?
P028GTOP009
P029RCL W
P030ENTER
P031INTG
P032RTN

計算結果

プログラムの実行結果は次のとおり。肝心の$\rho$についての和は8項にすぎないが、$\rho$を使わない計算と比べると計算精度が改善されている。下表のように加算する項数が0($\rho$を使わない),5,8と増えると誤差は減少する。10億未満の素数の個数は5000万個以上あるが、それが9個の誤差で得られているのはいい感じだ。

$x$
$\pi(x)$
$\pi(x)$と計算結果との差
計算時間
(秒)
0項5項8項
10025-1-1-135
1,000168-1-2-228
100,0009,592-41135
1,000,00078,49829191942
1,000,000,00050,847,534-79-66950
10,000,000,000455,052,511-1,827-817-33551
1,000,000,000,00037,607,912,018-1,475-2,629-347851

表末尾の$x=10^{12}$(10兆)では誤差の大小が逆転する。近似式の問題だろうか、それとも35sの有効桁数に近づいて計算誤差が累積しただろうか。計算時間は8項加算の時間だが、直線的に増えないのは、前述の$\mu(n)$関数の値によって計算量が不連続に変化することが影響していると思われる。途中経過の表示をやめると計算時間を5~10秒短縮できる。

印象と課題

HP35sのプログラム言語は、キーボードマクロに最小限の制御命令が追加されたコンパクトな仕様だが、メモリ参照命令が効果的で、素直に計算式をプログラム化できたことに感心した。計算速度もまあまあだ。課題は計算精度。近似式の検討、計算時間短縮のために省略した項や和の打ち切りなどを上手に処理できれば精度の向上が期待できる。次の機会に考えてみよう(いつになるやら)。

感想

素数の個数が実数や複素数の関数計算で求められることは、やはり不思議な感じがする。150年以上数学者の挑戦を跳ね返し続けているリーマン予想、そのややこしい式が手のひらで計算できるのを見たら、リーマン先生も面白がってくれるだろう。

Macintosh SE/30

Macintosh SE/30を購入したのは社会人としてまだ駆け出しの頃だった。購入して5年ほどで電源が入らなくなってしまい物置に入れたまま気がついたら30年以上経過していた。old macの復元も面白いテーマではあるが、仮に復元しても使い道が思い浮かばない。しばらく前から回路部...