今日も、やりかけのシェルピンスキー数について、やっていこうかと思う。
C言語を使って、
kを1から78557までの奇数となるようにループし、
k*2n+1が64ビット正整数の範囲でのすべての正の整数nに対して、
√k*2n+1以下の素数(または3以上の奇数)の剰余が、
0なら合成数でループから脱出、
合成数でなくループが終了したら素数、
とやっていき、
特定のnで素数になってしまったkは、シェルピンスキー数ではない。
つまり、候補から外せて、残ったkは、シェルピンスキー数の候補となる。
というプログラムを組んでみました。
#include <stdlib.h>
#include <math.h>
int main()
{
unsigned long long k,t,s,b,p,r;
int n;
for (k=1; k<=78557; k+=2) {
n = 1;
b = 2;
t = k*1+1;
s = k*b+1;
r = sqrtl(s)+1;
while ( t < s ) {
for (p=3; p<r; p+=2) {
if ( s%p == 0 ) break;
}
if ( s%p != 0 ) {
fprintf(stdout,"%llu\t%d\tPrime!\n",k,n,s);
fprintf(stderr,"%llu\t%d\tPrime!\n",k,n,s);
break;
}
n++;
t = s;
b *= 2;
s = k*b+1;
r = sqrtl(s)+1;
}
if ( t >= s ) {
fprintf(stdout,"%llu\t%d\tSierpinski?\n",k,n,s);
fprintf(stderr,"%llu\t%d\tSierpinski?\n",k,n,s);
}
}
return EXIT_SUCCESS;
}
unsigned long longを扱う上で、オーバーフロー検知が必要になります。
どのように判断するかというと、
nが増えるにつれて、sは大きくなるはずですよね。
なのに、小さくなってしまったら、それがオーバーフローなので、
一つ前のsをtとして保持しておき、t < sという条件が成り立っている間、
sの素数判定を、厳密に行いました。
k・2n+1が、64ビット正整数(unsigned long long)内までしか、素数判定していない状況で、これだけシェルピンスキー数候補があがったということです。
この中には、もう少し大きなnにすると、素数になる可能性があるものもあるのだろうが、
nが大きくなるにつれ、k・2n+1は指数的に大きくなり、素数判定も困難になっていきます。
今度は、多倍長演算LMで、フェルマーテストによる素数判定をはじめてみたが、
k・2n+1と確実に互いに素な値は2なので、
2k・2n≡1 (mod k・2n+1)
となれば、k・2n+1は素数の可能性がある。
合成数でも、この合同式が成り立つものがある。
2k・2n≢1 (mod k・2n+1)
となれば、k・2n+1は合成数である。
という方法はあっても、nが増えていくことはあっても、素数を確定するものではないので、先のC言語のプログラムよりも、シェルピンスキー数候補が減ることはない。
つまり、多倍長演算をしても、地道に素数判定をして、素数であることを確定する必要があるので、困難である。
先の記事のように、プログラミングで証明出来るようなものが作れるのかと言われると、おそらく難しいから、未だに未解決問題なのだろう。
ではでは