我学为我AP计算机科学期末考试,我碰到这个问题就来了:为什么这个程序的输出是-1?
int sum = 0, p = 1;
for (int count = 1; count <= 50; count++)
{
sum += p;
p *= 2;
}
输出为-1;但我不明白为什么会是这样。如果有人能向我解释这将是非常棒的。
我学为我AP计算机科学期末考试,我碰到这个问题就来了:为什么这个程序的输出是-1?
int sum = 0, p = 1;
for (int count = 1; count <= 50; count++)
{
sum += p;
p *= 2;
}
输出为-1;但我不明白为什么会是这样。如果有人能向我解释这将是非常棒的。
补充以前的答案。
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只是一种确保:
“......正数和负数可以自然方式共存。”
Two's Complement可以将符号位为0的正数有符号整数X转换为负-X。
例如(使用8位):
0110 1001 is the 2^0 + 2^3 + 2^5 + 2^6 = 105
要获得-105表示,我们使用的补码,这是完成:
因此,在我们的例子中,-105会由下式表示:
翻转所有的位,所以0 - > 1和1 - > 0
0110 1001 -> 1001 0110
添加一个到的结果。
1001 0110 + 0000 0001 = 1001 0111
因此我们得到1001 0111
作为我们的-105
那么,如何这都涉及这个问题的代表性?
程序输出-1的原因是因为int是一个带符号的数字变量。正如前面提到的答案,该程序将填充为1的整数分配的32位。
,如果你把在打印语句,这样System.out.print(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, ....
如果你添加一个if语句时和去-1赶上计数的值,你会发现,它去为-1,权当数= 32。这是合理的,考虑到事实上,一旦你的程序在MSB或Sign Bit中填入1,那么32位数字ber被视为负数。
现在使用Two's Complement,我们可以利用这样一个事实确切知道负数是什么,不仅可以得到一个数的负表达式,而且如果给出一个负数,也可以得到正表示数。因此,我们有:
翻转所有的位,所以0 - > 1和1 - > 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
代表的数量。因此,我们发现,1111 1111 1111 1111 1111 1111 1111 1111
是-1表示。
[integer overflow](http://en.wikipedia.org/wiki/Integer_overflow) – amit