我想制作一个测试科拉茨猜想的脚本。更具体地说,目标是制作一个脚本,允许我输入一个非 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
更改时重新计算。
您还存在未加引号的变量扩展的常见问题,但它们不是您的问题。