先の記事で、
そもそも数が大きくなればなるほど平方数は少なくなるのだから、
m2 < n < (m+1)2
となるような、自然数mが見つかれば、nは平方数ではないとなる。
これも、mをすばやく見つけられればよいのだが、なかなか難しいのかもしれない。
と書いたが、これを実現してみた。
C言語のようなプログラミング言語であれば、どのレンジの値を求めるかによって、変数の型を決める。
例えば、正整数型であれば、
8ビット正整数型、16ビット正整数型、32ビット正整数型、64ビット整数型といったように、異なるレンジが用意されている。
仮に、
8ビット正整数型を unsigned short
16ビット正整数型を unsigned int
32ビット正整数型を unsigned long
64ビット正整数型を unsigned long long
とするならば、
unsigned long i, j;
unsigned long long n, k;
/* 何らかの処理でnに値が入る */
for (i=0x80000000, j=0x40000000; j>0; j>>=1) {
k = (unsigned long long)i*i;
if ( n < k ) {
i -= j;
} else if ( n > k ) {
i += j;
} else {
break;
}
}
if ( n == k ) {
/* nは平方数 */
} else {
/* nは平方数ではない */
}
思ったよりも簡単に書けました。
タイトルでも書いた通り、二分探索(バイナリサーチ)です。
sqrt関数を使っていませんので、浮動小数型の誤差に悩まされる心配もありません。
ビット数だけのループ回数で済みますので、先の記事のような可能性という曖昧な判定ではなく、完全に決定できますので、さんざん絞り込んだあげく、平方数の可能性ありとなって、sqrt関数を使って調べてみたら、平方数じゃなかった。といったことはありません。
プログラミングは楽しいねぇ。
ではでは
追伸:
プログラムで先の3個のアイゼンシュタイン三角形から整数三角形を作るの問題を解いていたんだが、Windows10の更新で、リブートしてました。
というわけで、こういう事態にも対処できるように、プログラムを組みなおしました。
現時点で150組ほどのデータがそろいました。
今後は、パラレルで何個も動かして、一気に数を出そうかと考え中。