假设我们有int n = 2 ^ 31
,然后是n-1 = 0111111111111111111111111111111
,这就是我在本地可以得到的。
我的猜测:首先将n
转换为long
->减法->切片以适合int
。
System.out.println(n);
System.out.println(Integer.toBinaryString(n-1) + " : " + Integer.bitCount(n-1));
System.out.println(n-1);
// output
-2147483648
1111111111111111111111111111111 : 31
2147483647
但是我发现没有规范可以验证我的猜测,有一些吗?
当算术运算得出的结果大于一个N位整数的最大值时,溢出会将结果减小为2的N次幂模,仅保留结果的最低有效位并有效地导致换行周围。
如果我的猜测是完全错误的,那么它实际上是如何工作的?我可以参考任何链接吗?
任何帮助将不胜感激:)
答案 0 :(得分:1)
这就是二进制补码算术的工作原理。
根据JLS §15.18.2,从2 ^ 31中减去1等于2 ^ 31加-1,
对于整数和浮点减法,总是这样
a-b
产生的结果与a+(-b)
相同。
还有
如果整数加法溢出,则结果为低阶 数学和的位数,以足够大的幅度表示 二进制补码格式。如果发生溢出,则指示 结果与两者的数学和的符号不同 操作数值。
现在,我们可以计算二进制值2 ^ 31和-1的总和。 2 ^ 31是一个1,后跟31个零,即2的补码中的-2147483648。 -1的补码为32的补码,所以我们有:
1000 0000 0000 0000 0000 0000 0000 0000
+1111 1111 1111 1111 1111 1111 1111 1111
如您所见,左边的最后一位溢出,但是根据第二段摘录,我们忽略了这一点。将所有这些加起来,我们得到:
0111 1111 1111 1111 1111 1111 1111 1111
即2147483647