通过移动一位产生一个整数。我可以走多远?
直到整数表示形式回绕为止(大多数shell中是默认值)。
64位整数通常在处环绕2**63 - 1
。
那0x7fffffffffffffff
或9223372036854775807
在十二月。
该数字“ +1”变为负数。
与相同1<<63
,因此:
$ echo "$((1<<62)) $((1<<63)) and $((1<<64))"
4611686018427387904 -9223372036854775808 and 1
之后,该过程再次重复。
$((1<<80000)) $((1<<1022)) $((1<<1023)) $((1<<1024)) $((1<<1025)) $((1<<1026))
结果取决于mod 64
移位值[a]。
[a]来自:英特尔®64和IA-32体系结构软件开发人员手册:第2卷计数被掩码为5位(如果在64位模式下使用REX.W,则为6位)。计数范围限制为0到31(如果使用64位模式和REX.W,则为63)。。
另外:记得$((1<<0))
是1
$ for i in 80000 1022 1023 1024 1025 1026; do echo "$((i%64)) $((1<<i))"; done
0 1
62 4611686018427387904
63 -9223372036854775808
0 1
1 2
2 4
因此,这完全取决于数字与64的倍数的接近程度。
测试极限:
测试最大正(和负)整数的有效方法是依次测试每一位。无论如何,对于大多数计算机而言,它的步数不到64,所以不会太慢。
重击
首先,我们需要形式最大的整数2^n
(1位,后跟零)。我们可以通过左移直到下一个移位使数字变为负数(也称为“环绕”)来实现:
a=1; while ((a>0)); do ((b=a,a<<=1)) ; done
b
结果在哪里:使循环失败的最后一个移位之前的值。
然后,我们需要尽一切努力找出哪些影响以下符号e
:
c=$b;d=$b;
while ((c>>=1)); do
((e=d+c))
(( e>0 )) && ((d=e))
done;
intmax=$d
最大整数(intmax
)由的最后一个值得出d
。
在不利的一面(小于0
),我们重复了所有测试,但测试何时可以将某位设置为0而不会回绕。
这是打印所有步骤的整体测试(对于bash):
#!/bin/bash
sayit(){ printf '%020d 0x%016x\n' "$1"{,}; }
a=1; while ((a>0)) ; do((b=a,a<<=1)) ; sayit "$a"; done
c=$b;d=$b; while((c>>=1)); do((e=d+c));((e>0))&&((d=e)) ; sayit "$d"; done;
intmax=$d
a=-1; while ((a<0)) ; do((b=a,a<<=1)) ; sayit "$b"; done;
c=$b;d=$b; while ((c<-1)); do((c>>=1,e=d+c));((e<0))&&((d=e)); sayit "$d"; done
intmin=$d
printf '%20d max positive value 0x%016x\n' "$intmax" "$intmax"
printf '%20d min negative value 0x%016x\n' "$intmin" "$intmin"
SH
翻译成几乎所有的shell:
#!/bin/sh
printing=false
sayit(){ "$printing" && printf '%020d 0x%016x\n' "$1" "$1"; }
a=1; while [ "$a" -gt 0 ];do b=$a;a=$((a<<1)); sayit "$a"; done
c=$b;d=$b; while c=$((c>>1)); [ "$c" -gt 0 ];do e=$((d+c)); [ "$e" -gt 0 ] && d=$e ; sayit "$d"; done;
intmax=$d
a=-1; while [ "$a" -lt 0 ];do b=$a;a=$((a<<1)); sayit "$b"; done;
c=$b;d=$b; while [ "$c" -lt -1 ];do c=$((c>>1));e=$((d+c));[ "$e" -lt 0 ] && d=$e ; sayit "$d"; done
intmin=$d
printf '%20d max positive value 0x%016x\n' "$intmax" "$intmax"
printf '%20d min negative value 0x%016x\n' "$intmin" "$intmin"
对许多shell运行以上命令,
所有(bash 2.04和mksh除外2**63 -1
)在此计算机中接受的值最多为()。
报告att外壳很有趣:
$ attsh --version
version sh (AT&T Research) 93u+ 2012-08-01
在$((2^63))
,而不是ksh的值上显示错误。