我正在攻读AP计算机科学的期末考试,我遇到了这个问题:
int sum = 0, p = 1;
for (int count = 1; count <= 50; count++)
{
sum += p;
p *= 2;
}
输出为-1;但是我不明白为什么会这样。如果有人能向我解释这将是非常棒的。
答案 0 :(得分:6)
答案 1 :(得分:0)
补充先前的答案。
java中的整数由32 bits表示。因此,很容易看出可以用int表示的最大值是:
1111 1111 1111 1111 1111 1111 1111 1111 (which is 32 1's)
这个值相当于:
(1)*2^0 + (1)*2^1 + (1)*2^2 + ... + (1)*2^31 = 2^32 - 1 = 4294967295
但是,整数如何代表负数?
答案是上述计算和限制仅适用于使用32位表示的无符号值。
负数用Sign Bit表示,对应最左边的位或MSB or Most Significant Bit。
另外,由于有符号数字需要留出一点来跟踪符号,有符号数字永远不能代表大于无符号数字的数字,只是因为它们的位数较少。
知道MSB只是签名值的符号位,我们如何找出实际数字是什么?
答案是使用Two's Complement。根据维基百科的说法,Two's Complement只是一种确保:
的方法&#34; ...正面和负面数字可以自然地共存。&#34;
两个补码可以将符号位为0的正有符号整数X转换为负-X。
例如(使用8位):
0110 1001 is the 2^0 + 2^3 + 2^5 + 2^6 = 105
为了获得-105的表示,我们使用了两个补语,其完成时间为:
因此在我们的示例中,-105将表示为:
翻转所有位,所以0 - &gt; 1和1 - &gt; 0
0110 1001 -> 1001 0110
在结果中添加一个。
1001 0110 + 0000 0001 = 1001 0111
因此我们得到1001 0111
作为-105
那么这一切如何与这个问题联系起来呢?
程序输出-1的原因是因为int是带符号的数字变量。正如之前的回答所提到的那样,程序填充了为1和分配的32位的32位。
如果你输入print语句就可以很好地看到这一点,就像这个System.out.print(sum + ", ");
在循环继续时打印出sum的值,你最终看到的是这样的:
1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
二进制是:
1, 11, 111, 1111, 1 1111, ....
如果在sum变为-1时添加一个if语句来捕获count的值,你会发现当count = 32时它会变为-1。这是有道理的,因为一旦你的程序填充了这个事实在MSB或符号位中为1,32位数被视为负数。
现在使用Two's Complement,我们可以通过利用这样一个事实来确切地知道该负数是什么,这样你不仅可以获得数字的负面表示,而且如果你是给出一个负数。因此,我们有:
翻转所有位,所以0 - &gt; 1和1 - &gt; 0
1111 1111 1111 1111 1111 1111 1111 1111 -> 0000 0000 0000 0000 0000 0000 0000 0000
在结果中添加一个。
0000 0000 0000 0000 0000 0000 0000 0000 + 0001 = 0001
代表数字1.因此,我们发现1111 1111 1111 1111 1111 1111 1111 1111
是-1的表示。