我學爲我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