我很好奇,当 bash 中的数字变量增加而不故意停止时会发生什么。数字会变得多大?它会溢出并变为负数,然后继续永远增加吗?它会在某个时刻中断并停止吗?
我使用的是 x86_64 AMD 处理器,但我也很乐意听到 32 位答案,只需指定您所说的内容即可。我正在运行 Fedora21 64 位。
我搜索了好多地方,但不知为何没有找到这个具体信息。它似乎是所有手册等中的一条基本信息。
答案1
这可能取决于您的 bash 版本、操作系统和 CPU 架构。您为什么不自己尝试一下?将变量设置为 (2^31)-1,然后将其递增,将其设置为 2^32,然后递增,将其设置为 2^64,然后递增,等等。
在这里,我刚刚在运行 OS X“El Capitan”v10.11.3 的 Core i7 Mac 上亲自尝试了一下,看起来 bash 正在使用有符号的 64 位整数。
$ uname -a Darwin Spiff.local 15.3.0 Darwin 内核版本 15.3.0:2015 年 12 月 10 日星期四 18:40:58 PST;root:xnu-3248.30.4~1/RELEASE_X86_64 x86_64 $ bash --version bash --version GNU bash,版本 3.2.57(1)-发布(x86_64-apple-darwin15) 版权所有 (C) 2007 自由软件基金会,Inc. $ $((X=2**16));回显 $X 65536 <- 好的,至少是 UInt16 $((X=2**32));回显 $X 4294967296 <- 好的,至少是 UInt32 $((X=2**64));回显 $X 0 <-- 哎呀,不是 UInt64 $((X=(2**63)-1));回显 $X 9223372036854775807 <- 好的,至少是 SInt64 $((X ++));回显 $X -9223372036854775808 <-- 溢出并包装为负数。必须是 SInt64
答案2
我设置了一个循环。while return status is 0 increment a variable with addition and print the variable to stdout
我从略低于 2^31 的位置开始,让它毫无问题地通过 2^31 和 2^32,然后停止它,然后将初始值设置为略低于 2^63。结果是它无缝地从 9.22e18 滚动到 -9.22e18 并继续正向递增。(趋向于零)
只是为了检查我while [ $? -eq 0 ]
是否实际使用了 while 循环中命令的退出状态,而不是使用前一个脚本的退出状态或某些奇怪的东西,我还在循环中使用一个额外的命令运行它,旨在在特定增量处创建非零退出状态。
因此它是有符号的,它会继续循环而不是在最大值处停止,而且它不会出现任何错误消息。因此它有可能陷入真正的无限循环。它不会将 64 位硬件和 64 位 Linux 操作系统限制为旧的 16 位或 32 位标准。
答案3
我改进并自动化了@Spiff 的答案:
MAX_INT=0
for ((x=1,y=1; x<<=y; y<<=1))
do
if ((x>0))
then
MAX_INT=$x
continue
fi
if (((x=~x)>0))
then
MAX_INT=$x
fi
break
done
echo $MAX_INT
答案4
获取最大 bash 整数(maxI)和最小 bash 整数(minI)的命令:
$ maxI=$( echo `printf "%u" -1` / 2 | bc )
$ echo $maxI
9223372036854775807
$ minI=$(($maxI + 1))
$ echo $minI
-9223372036854775808
在不同的机器上结果可能会不一样,但是命令应该是一样的。
- 更新 -
更短的 maxI(删除多余的“回声”),以及更“精确”的 maxI:
$ maxI=$( printf "%u/2\n" -2 | bc )
$ echo $maxI
9223372036854775807
使用 -2 比使用 -1 更精确,其中,printf "%u" -1
在我的计算机上给出 18446744073709551615,不能被 2 整除,尽管 bc 给出了正确的答案 9223372036854775807,因为 bc 截断了小数点后的任何数字。(因为默认的“scale”变量为零)。使用 -2,它现在将是 18446744073709551614,可以被 2 整除,并且在除法时给出正确的答案。