Koracの推測をテストするスクリプトを作成したいと思います。より具体的には、目標は1以外の正の整数を入力できるスクリプトを作成し、Collatzアルゴリズムが完了すると1になると予想される最後の数字を印刷することです。
任意の正の整数 n を取ります。 nが偶数の場合、nを2で割ってn / 2を取得します。 nが奇数の場合、nに3を掛けて1を加えて3n + 1になります。このプロセスを無限に繰り返してください。どんな数字から始めても、最終的に1に達すると推測されます。
これが私の試みです -
echo "Enter in a positive integer greater than 1"
read n
let "r=$n%2"
if [ $n -le 1 ]
then
echo "Error: you must enter in a positive integer greater than 1"
exit
fi
while [ $n -ne 1 ]
do
if [ $r == 0 ]
then
let "n=$n/2"
echo $n
fi
if [ $r -ne 0 ]
then
let "n=3*$n + 1"
echo $n
fi
done
echo $n
2 と入力すると 1 が表示されます。これは望ましい結果です。ただし、3の値を読み取ると、次のような無限ループが発生します。
931947686741790850
2795843060225372551
8387529180676117654
6715843468318801347
1700786331246852426
5102358993740557279
-3139667092487879778
9027742796245912283
.
.
.
など。
私の正確な質問は次のとおりです。私のコードに問題がありますか?大きな数字を印刷する原因は何ですか?
答え1
これ:
let "r=$n%2"
...
while [ $n -ne 1 ]
do
if [ $r == 0 ]
...
done
r
ループ外で一度だけ割り当てます。
ほとんどのプログラミング言語では、割り当てと同じことは、y = f(x)
「現在の値を取得しx
てf(x)
計算を実行してから結果をコピーするy
」ことを意味します。これは、「今から永遠までy
常に同じでなければならない」という数学的な説明とは異なりますf(x)
。コードでは、n
次のようには機能しません。値を変更し、ループの複数の反復で異なるように依存します。
r
したがって、最初の数値から得られた値はループ全体にわたって保持され、ループが繰り返されるたびに同じ操作を繰り返すことができます。もちろん、トリプルサークルは膨大な数に達し、あふれ始めます。
解決策は簡単です。割り当てをr
ループ内に移動して、n
変更されるたびに再計算するようにします。
また、引用されていない変数拡張の一般的な問題がありますが、これは問題ではありません。