コラッツ予想とは
ある自然数に関して偶数なら2で割る、奇数なら3かけて1足すという動作を繰り返すと、どんな自然数でもいつかは1になるという予想であり、数学の未解決問題のひとつ。
数学的な言い方をすると、
コラッツ予想とは、関数fをmが奇数ならばf(m)=(3m+1)/2,偶数ならばf(m)=m/2と定義すると、任意の自然数mについてf^n(m)=1となるようなnが存在する、という予想である。
引用:コラッツ予想について
詳しくは、Wikipediaの記事を見ていただきたい。
コラッツ予想に対する私の考え
無限に存在する自然数の中で、こんな簡単な予想から外れる数がひとつも存在しないなんて、事実なら凄く夢のある話である。仮に事実でなく、反例が存在するならどういう理屈で反例となっているのか、想像ができない。小3くらいの頃からずっと関心を持っているものであり、出来ることなら自力で解決してしまいたい。
しかし、タイトルとも直前の発言とも矛盾してしまうのだが、率直に私には解決できるようなものではないと思う。
以下の記事を見ていただきたい。
参照:数学の未解決問題「コラッツ予想」に1億2000万円の懸賞金
2021年7月7日、このコラッツ予想に1億2000万円の懸賞金がかけられたのである。
これまでたくさんの数学者や暇人がこの未解決問題に対して取り組んできたにもかかわらず、未だに解決していない。当然懸賞金がかけられてから約1年経った今でも、まだ謎に包まれたままである。
しかし、解決することでお金が、しかも大金が!!
やってみよう!!というくらいの軽い考えである。
C言語で演算コードを作って、効率的に検証してみた
まずは検証してみよう!ということで、優秀な計算機であるc言語を用いて検証してみる。
手計算でも良いのだが、機械に計算を任せることで、より効率的に検証できるため、プログラムをした。
1. コラッツ予想の概要通りの計算方法
以下が実際に作ってみたコード。
#include<stdio.h>
int main(void){
int a,i,n;
printf("n= ");
scanf("%d",&n);
for(i=n;i<n+10;i++){//nの値を変えることでその値からその値+9までの10つの自然数に関して同時に検証する
a=i;
printf("%d %d→", a, a);
while(a!=2){//aが2でないとき以下の動作を繰り返す。
if(a%2 == 1){//aが奇数なら
a = a*3+1;//aを3で割って1足す。
}
else{//aが偶数なら
a /= 2;//aを2で割る。
}
printf("%d→",a);//出力:数値→
}
printf("1\n\n");
}
getchar();
getchar();
return 0;
}
皆さんにも実際にこのコードをコピペして、自分の誕生日などで動かしていただきたい。
実際に試してみると、この数は1になるまで思ったより長くかかるなあとか小さな感動を得られる(得られない?)。
このコード自体は偶然反例となる数を検証に用いること以外で、コラッツ予想の正誤やその証明に役立つことはない。
しかし、検証結果が一般的な人間視点で見やすい点では優秀である。
2. 2進数による計算
数を2進数で表してしまえば、その整数倍は0,1で遊ぶことで求められ、計算をより視覚的に行い、また簡略化できると考えた。
また、偶奇の判断を、「1の位が2で割れるか否か」ではなく、最下位ビット(2^0の位)が0か1かで行うことが出来る。
例えば1152
という数があったとして、これをそのまま2で割り続けて奇数になったら3掛けて1足して…と計算するより、2進数で10010000000
と表現することで、2^0の位が1になるまでそのまま右にズラした方が圧倒的に楽である。
この数字に関して言えば、1度の操作で、2^7=128
で割ることができ、普通に計算するより6回分も手順が少なくて済む。
また、奇数である1001
については、10進数で「3を掛けて1足す」という処理を行えばよいので、2進数で言えば、「(1001を左に1ビットシフトした数)+1001+1」
という処理を行う。
この考え方でコラッツ予想の検証が出来るコードを作った。以下コード。
#include<stdio.h>
int main(void){
int i, j=0, arr[100], n;
for(i=0;i<=99;i++){//配列の要素を一旦すべて2にする
arr[i]=2;
}
printf("自然数を入力してください。: ");
scanf("%d",&n);
while(n!=0){//2進数変換
arr[j] = n%2;
n = n/2;
j++;
}
for(j=0;arr[j]<2;j++){//2が出るまで出力
printf("%d", arr[j]);
}
printf("\n");
while(!(arr[0]==1 && arr[1]==2)){//終了条件(1)を満たさないとき繰り返す
if(arr[0]==0){//偶数なら
for(j=0;j<=98;j++){//シフト
arr[j]=arr[j+1];
}
for(j=0;arr[j]<2;j++){//2が出るまで出力
printf("%d", arr[j]);
}
printf("\n");
}else if(arr[0]==1){
for(j=99;j>=1;j--){//2を0に戻す
if(arr[j]==2){
arr[j]=0;
}
}
for(j=99;j>=1;j--){//3倍する
arr[j]=arr[j-1]+arr[j];
}
arr[0]+=1;//1足す
for(j=0;j<=98;j++){//繰り上がりの処理
if(arr[j]==3){
arr[j]=1;
arr[j+1]+=1;
}else if(arr[j]==2){
arr[j]=0;
arr[j+1]+=1;
}
}for(j=99;arr[j]!=1;j--){//あまりをすべて2にする
arr[j]=2;
}
for(j=0;arr[j]<2;j++){//2が出るまで出力
printf("%d", arr[j]);
}
printf("\n");
}
}
return 0;
}
上手い書き方が思いつかずかなり汚いコードにはなっていると思いますが、ご了承ください。
とりあえずEclipseでは問題なく動きそうです。
このコードを書いている最中で1つ反例を見つけだすアイデアを思いついたので、次の節でそれについて考える。
全体、もしくは下何桁かでループさせることができれば、その数は永遠に1にならないのでは
ループするための条件は、
① ループさせたい桁より上の桁が、ループさせたい桁に影響を及ぼさない
または、
② ループさせたい桁より上の桁がループさせたい桁に影響を及ぼした結果、ループする
である。
無限という概念を用いてよいのであれば、条件①を満たすものとしてひとつ簡単に思いつくものがある。
100...(無限個の0)...001
と言う数が、下3桁が
001
、100
、010
、001
とループし、尚且つそれより上の桁で直近の1は無限に離れているため、下3桁のループに影響せず、無限に1となることはない。(無限vs無限の戦いになることには目を瞑っていただきたい。)
有限の範囲内で考えると、計算の過程でループさせたい桁より上の桁がジワジワと下の桁に侵食してくるため、条件①を満たすものは存在しないだろう。
条件②について考える。
ループさせたい桁が2進数で5桁だとして、5桁への、それより上の桁からの影響が一定でなければ、ループし続けることは不可能だと考える。
10進数で数式で考えてみる
条件②について、背理法を使って、簡単なものから順にひたすら反例の存在可能性を否定していこうと思う。
背理法
・・・ある主張を証明するのに、その主張が正しくないと仮定して矛盾を導くことで行う証明方法のこと
参照:【3分で分かる!】背理法の使い方と証明の書き方をわかりやすく(練習問題付き)
ここで、以下、xは3以上の奇数である
とする。
また、xを3倍して1足す。その後、2で割る
の流れを1巡
とする。
- 1巡後にxになるxが存在すると仮定すると、
以下の等式が成り立つxが存在する。
(3x+1)/2 = x
これを解くと、x=-1
これはx>=3に反するため、1巡後にxになるxは存在しない。
(蛇足だが、-1について1巡の動作を行うと、-1に戻る。面白い。)
- 1巡後2で割るとxになるxが存在すると仮定すると、
以下の等式が成り立つxが存在する。
(3x+1)/2^2 = x
これを解くと、x=1
これはx>=3に反するので、1巡後2で割るとxになるxは存在しない。
(x=1の場合確かに1,4,2,1,4,2,1,...とループはするのだが、x=1の時点で反例ではない。)
- 1巡後2で割り、再度2で割る(2^2で割る)とxになるxが存在すると仮定すると、
以下の等式が成り立つxが存在する。
(3x+1)/2^3 = x
これを解くと、x = 0.2
これはx>=3に反するので、1巡後2^2で割るとxになるxは存在しない。
これ以上2で割る回数を増やしても、xの値が0に近づいていく限りであるので、2巡することにする。
- 2巡後にxになるxが存在すると仮定すると、
以下の等式が成り立つxが存在する。
(((3x+1)/2)*3+1)/2 = x
これを解くと、x=-1
これはx>=3に反するので、2巡後にxになるxは存在しない。
・
・
・
・
結論:果てしない。
この未解決問題に取り組んでいて、常に感じていたことだ。
ひたすらにこの未解決問題は果てしない。
今回この記事を通して伝えたかったことはそんなことではなく、今回取り上げた「コラッツ予想」のほかにも、有名どころでは「ゴールドバッハ予想」、「素数(合成数)であるフェルマー数は無数個(有限個)存在するか」など、数学の未解決問題はいまだ多数存在している。
今回、数学に触れていない人にもわかりやすい内容のものを選んで紹介したが、夜通し考えてしまうほど面白い問題が多数存在しており、私は一人でも多くの人にその存在を知っていただきたい。
また、コラッツ予想は私が特に興味を持っている未解決問題であり、少しでも解決に近づいたら良いなと思っている(影響力が雀の涙ほどもないが)。
下にWikipediaのリンクを貼っておくので、興味のある方はぜひ一度クリックしてみていただきたい。
参照:数学上の未解決問題
ここまで読んでくださった方、また飛ばして結論だけでも読んでくださった方、本当にありがとうございます。
言葉不足、知識不足で読みづらい文章だったと思います。
少しでも好奇心を駆り立てるきっかけになれていましたら幸いです。