Google ClassroomGoogleクラスルーム
GeoGebraGeoGebra Classroom

1度あることは2度あるのか?

このワークシートはMath by Codeの一部です。
素数というのはとりあえず、2,3,5、…と存在するわけだし、 無限に続くこともわかっている。 しかし、素数の空白地帯がベターっと続く可能性があることもわかっている。 それに、素数の濃度は1/logN≒π(N)/Nで、素数は先にいけばいくほど濃度が薄くなっていく。 (ガウスの理論からπ(N)≒N/logN ) さらに、素数の分布は予想がつかないほど不規則なのだ。 さて、どんな自然数Nを指定されてもN以下に素数があることはもちろん当然で何の話題にもならない。 そうではなく、次の長さNの整数たち、 つまり、Nを超えて2Nまでの整数は空白になることはないのだろうか? ならない。 これをベルトランさんが主張した。 ベルトランの予想は、「どんな自然数Nでも、Nより大きく2N以下の素数が必ずある。」 Nから先の2Nまでは素数砂漠が奇跡的に存在する、 そんな巨大数Nはありえないのか???

1.素数分布をさぐるチェビシェフの道具

チェビシェフさんは素数の分布を独自の道具を使って分析した。 その道具は2つある。 N以下の素数をpとするとき、その自然対数の和をθ(N)とする。 第1関数θ(N)=Σlogp N以下の1素数のべきをP^aとするとき、その自然対数の和をψ(N)とする。 第2関数ψ(N)=Σlogp こんなに省略してしまうと、なんだかわからないでしょうから、例を出そう。 Nまでの素数の個数をπ(N)とかくことにする。 N=10なら π(N)=4. θ(N)=log2+log3+log5+log7=log(2・3・5・7)=log210 2のべきは最大8で3個、3のべきは最大9で2個あるから、 ψ(N)=3log2+2log3+log5+log7=log(8・9・5・7)=log2520 π(2N)=8. θ(2N)=log(210・11・13・17・19) ψ(2N)=log(16・9・5・7・11・13・17・19) π(2N)-π(N)=8-4=4>0 θ(2N)-θ(N)=log(210・11・13・17・19/210)=log(11・13・17・19) ψ(2N)-ψ(N)=log(16・9・5・7・11・13・17・19/(8・9・5・7))=log(2・11・13・17・19) もしも、Nをこえて2Nまでに素数が空白になるとどうなるだろうか? π(2N)-π(N)=0はもちろんだ。 θ(2N)-θ(N)=log1=0 ψ(2N)-ψ(N)=log1=0 logを使うことで、logA-logA=logA/A=log1=0となるから、素数空白地帯があればベルトランさんの 意図に反して、どの関数の差も=0になるということだね。 課題:コードで3関数の挙動をしらべるにはどうしますか。 Nを倍々にふやしながら、2NとNとでの差を比較してみよう。 どれだけNの増大に連動するかがわかる。 例 [IN]Python import numpy as np from sympy import primerange, primefactors from sympy import primepi def chebyshev_f(N): primes = list(primerange(2, N + 1)) # 1. 第1関数 chevy1(N) = Σ log(p) th = sum(np.log(p) for p in primes) # 2. 第2関数 chevy2(N) ps = 0 for p in primes: a = 1 while p ** (a + 1) <= N: a += 1 ps += np.log(p ** a) return th, ps def bertrand_report(N): th1N,ps1N = chebyshev_f(N) th2N,ps2N = chebyshev_f(2 * N) pi1N = primepi(N) pi2N = primepi(2 * N) diff_0 = pi2N - pi1N diff_1 = th2N - th1N diff_2 = ps2N - ps1N print("-" * 5,end="") print(f"【N = {N}】",end="") print("-" * 20) print(f" π(2N) - π(N) = {diff_0:.4f})") print(f" θ(2N) - θ(N) = {diff_1:.4f} (指数化: e^diff = {np.exp(diff_1):.1f})") print(f" ψ(2N) - ψ(N) = {diff_2:.4f} (指数化: e^diff = {np.exp(diff_2):.1f})") bertrand_report(10) bertrand_report(20) bertrand_report(40) bertrand_report(80) [OUT] -----【N = 10】-------------------- π(2N) - π(N) = 4.0000) θ(2N) - θ(N) = 10.7405 (指数化: e^diff = 46189.0) ψ(2N) - ψ(N) = 11.4336 (指数化: e^diff = 92378.0) -----【N = 20】-------------------- π(2N) - π(N) = 4.0000) θ(2N) - θ(N) = 13.5477 (指数化: e^diff = 765049.0) ψ(2N) - ψ(N) = 16.9489 (指数化: e^diff = 22951470.0) -----【N = 40】-------------------- π(2N) - π(N) = 10.0000) θ(2N) - θ(N) = 40.6109 (指数化: e^diff = 433601713048865408.0) ψ(2N) - ψ(N) = 43.2500 (指数化: e^diff = 6070423982684139520.0) -----【N = 80】-------------------- π(2N) - π(N) = 15.0000) θ(2N) - θ(N) = 71.4749 (指数化: e^diff = 10994118229824091706491928576000.0) ψ(2N) - ψ(N) = 77.2740 (指数化: e^diff = 3628059015841991308949340284780544.0) <振り返り> π関数は現実のカウントなので、不規則性があり、がたがたするのはしかたない。 でも、πは調べただけだからただのラベルであり、中身がない。 その中身を理想化したのがθとψだ。 Nが倍々に範囲拡大すると、チェビシェフ関数は両方とも倍々に近く増大するため 2NとNの関数差もNの範囲拡大に比例して増大しているように見える。 この直線に近い反応のよさ これから、不規則な現実であるπをきれいな直線に近い直線で予測してくれるようすがわかる。 もちろん、そのまま同じになるという近似ではない。 しかし、指数化することで、そのなめらかな増加が手にとるようにわかる。 こんな変化からいきなり2NとNの関数差がぼこっと0になることがあり得ない ということが この実験だけでわかるでしょう。 チェビシェフさんは、さらにθ(x)については、正の定数A,Bがあって、2直線y=Axとy=Bxで 挟み込み、Ax<θ(x)<Bxができることを証明した。チェビシェフ不等式という定理だ。 ベルトランさんのときはただの予想だったものが、 ベルトラン・チェビシェフの定理となった。「2以上のxに対して2と2xの間には必ず素数がある。」 つまり、チェビシェフさんは証明できたということですね。 さっき、π(x)は不規則な現実であり、θ(x)、ψ(x)はなめらなな直線みたいだが理論であり、 しかも大きさがちがうとかいた。 こんな現実離れしたものがなぜ大事なのか。 それは、logxで割ると現実に即している関数になるからだ。 それが、チェビシェフ関数定理でx→∞のとき、θ(x)/logx, ψ(x)/logxともに→π(x) というものだ。 差ではなく、関数そのもので確かめてみよう。
課題:チェビシェフ関数定理を実感するにはどうしたらよいですか。 調べる範囲を100倍ごとに大きくしてみましょう。 ガウスの理論値π(x)=x/logxととも比べると チェビシェフ関数のよさに確信が持てるでしょう。 import numpy as np from sympy import primerange, primefactors from sympy import primepi import math def chebyshev_f(N): primes = list(primerange(2, N + 1)) # 1. 第1関数 chevy1(N) = Σ log(p) th = sum(np.log(p) for p in primes) # 2. 第2関数 chevy2(N) ps = 0 for p in primes: a = 1 while p ** (a + 1) <= N: a += 1 ps += np.log(p ** a) return th, ps def pi_report(N): thN,psN = chebyshev_f(N) piN = primepi(N) logN = math.log(N) print("-" * 5,end="") print(f"【N = {N}】",end="") print("-" * 20) print(f" π(N) = {piN:.4f})") print(f" N/log(N) = {N/logN:.4f})") print(f" θ(N)/log(N) = {thN/logN:.4f})") print(f" ψ(N)/log(N) = {psN/logN:.4f})") pi_report(10) pi_report(1000) pi_report(100000) pi_report(10000000) [OUT] -----【N = 10】-------------------- π(N) = 4.0000) N/log(N) = 4.3429) θ(N)/log(N) = 2.3222) ψ(N)/log(N) = 3.4014) -----【N = 1000】-------------------- π(N) = 168.0000) N/log(N) = 144.7648) θ(N)/log(N) = 138.4307) ψ(N)/log(N) = 144.2843) -----【N = 100000】-------------------- π(N) = 9592.0000) N/log(N) = 8685.8896) θ(N)/log(N) = 8658.5629) ψ(N)/log(N) = 8690.3684) -----【N = 10000000】-------------------- π(N) = 664579.0000) N/log(N) = 620420.6884) θ(N)/log(N) = 620121.6033) ψ(N)/log(N) = 620330.0700) <振り返り> 桁数が同じであること、 そして、最大桁の数字が同じになり、 次の桁の数字も近づく様子から、π(x)の近似関数になりうることが実感できるでしょう。 なによりも、「ガウスの理論値とはほぼ一致」といってよい精度ですね。 チェビシェフ関数定理を言い換えると (x→∞のとき、θ(x)/logx, ψ(x)/logx → x/logx) とかけるから、 logN倍すれば、 x→∞のとき、θ(x), ψ(x)→x つまり、チェビシェフ関数は両方とも y=xに近づくということだ。 なんて、単純で美しいのだろうか。 課題:geogebraで、チェビシェフ第一関数が直線的に変化することを確かめよう。 n = slider(10,10000,10) nums = Sequence(a,a,1,n) primes = Keepif(IsPrime(a),nums) chevy1= sum(zip(ln(a),a,primes)) #log10ではなく、自然対数ln y=x (n,chevy1) y=chevy1/n x グラフのメモリをx、yともに15000まで第一象限が見えるように設定して nをアニメーションしてみよう。 n=10000のオーダーでは、 y=xとy=chevy1/n xは隙間が多少あるものの 直線的な変化とほぼ重なる感じがみられるね。 理論値とはいえ、これが凹っと0になることが巨大数で起こることは、 証明せずともありえないという感じがしますね。 この検証から、 素数たちが隙間を作りながらも、はるかかなたでも巨大な真空をつくらずに存在を 続けるエネルギーを感じますね。 まっすぐに広がる素数空間のエネルギーです。 ということで、 証明はチェビシェフさんやラマヌジャンさんなどの数学の専門家におまかせしておきましょう。

チェビシェフ第一関数