22 bash arithmetic
这是一个探索性问题,这意味着我不完全确定这个问题是关于什么的,但我认为它是关于 Bash 中最大的整数。无论如何,我会明示地定义它。
$ echo $((1<<8))
256
Run Code Online (Sandbox Code Playgroud)
我通过移动一点来产生一个整数。我能走多远?
$ echo $((1<<80000))
1
Run Code Online (Sandbox Code Playgroud)
显然没有那么远。(1 是出乎意料的,我会回到它。)但是,
$ echo $((1<<1022))
4611686018427387904
Run Code Online (Sandbox Code Playgroud)
仍然是积极的。然而,不是这个:
$ echo $((1<<1023))
-9223372036854775808
Run Code Online (Sandbox Code Playgroud)
再往前走一步,
$ echo $((1<<1024))
1
Run Code Online (Sandbox Code Playgroud)
为什么是 1?为什么会出现以下情况?
$ echo $((1<<1025))
2
$ echo $((1<<1026))
4
Run Code Online (Sandbox Code Playgroud)
有人想分析这个系列吗?
更新
我的机器:
$ uname -a
Linux tomas-Latitude-E4200 4.4.0-47-generic #68-Ubuntu SMP Wed Oct 26 19:39:52 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
Ste*_*itt 32
Bash使用intmax_t变量进行算术运算。在您的系统上,这些长度为 64 位,因此:
$ echo $((1<<62))
4611686018427387904
Run Code Online (Sandbox Code Playgroud)
这是
100000000000000000000000000000000000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)
二进制(1 后跟 62 个 0)。再转移一下:
$ echo $((1<<63))
-9223372036854775808
Run Code Online (Sandbox Code Playgroud)
这是
1000000000000000000000000000000000000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)
二进制(63 0),二进制补码算法。
要获得最大的可表示整数,您需要减去 1:
$ echo $(((1<<63)-1))
9223372036854775807
Run Code Online (Sandbox Code Playgroud)
这是
111111111111111111111111111111111111111111111111111111111111111
Run Code Online (Sandbox Code Playgroud)
以二进制形式。
正如ilkkachu的回答中所指出的,在64 位x86 CPU(无论是使用RCL还是SHL)上,移位采用偏移模 64 ,这解释了您所看到的行为:
$ echo $((1<<64))
1
Run Code Online (Sandbox Code Playgroud)
相当于$((1<<0))。因此$((1<<1025))是$((1<<1)),$((1<<1026))是$((1<<2))...
您将在stdint.h; 中找到类型定义和最大值。在您的系统上:
/* Largest integral types. */
#if __WORDSIZE == 64
typedef long int intmax_t;
typedef unsigned long int uintmax_t;
#else
__extension__
typedef long long int intmax_t;
__extension__
typedef unsigned long long int uintmax_t;
#endif
/* Minimum for largest signed integral type. */
# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1)
/* Maximum for largest signed integral type. */
# define INTMAX_MAX (__INT64_C(9223372036854775807))
Run Code Online (Sandbox Code Playgroud)
来自2.05b的CHANGES文件bash:
j. shell 现在以机器支持的最大整数大小 (intmax_t) 执行算术,而不是 long。
在 x86_64 机器上intmax_t对应于有符号的 64 位整数。因此,您会在-2^63和之间获得有意义的值2^63-1。在这个范围之外,你只会得到环绕。
| 归档时间: |
|
| 查看次数: |
23264 次 |
| 最近记录: |