为什么这个程序的输出为-1?

时间:2015-04-28 17:07:14

标签: java

我正在攻读AP计算机科学的期末考试,我遇到了这个问题:

int sum = 0, p = 1;
for (int count = 1; count <= 50; count++)
{
    sum += p;
    p *= 2;
}

输出为-1;但是我不明白为什么会这样。如果有人能向我解释这将是非常棒的。

2 个答案:

答案 0 :(得分:6)

通过添加1,2,4,8,...,您基本上用1填充sum的二进制表示。

由于111..1-1的表示,因此您实际上会生成此数字。

这通常被视为Integer Overflow

答案 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

  • 如果Sign Bit = 1,如110,则数字为负
  • 反之亦然

另外,由于有符号数字需要留出一点来跟踪符号,有符号数字永远不能代表大于无符号数字的数字,只是因为它们的位数较少。

知道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的表示,我们使用了两个补语,其完成时间为:

  1. 翻转所有位,所以0 - &gt; 1和1 - &gt; 0
  2. 在结果中添加一个
  3. 因此在我们的示例中,-105将表示为:

    1. 翻转所有位,所以0 - &gt; 1和1 - &gt; 0

      0110 1001 -> 1001 0110
      
    2. 在结果中添加一个。

      1001 0110 + 0000 0001 = 1001 0111
      
    3. 因此我们得到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,我们可以通过利用这样一个事实来确切地知道该负数是什么,这样你不仅可以获得数字的负面表示,而且如果你是给出一个负数。因此,我们有:

      1. 翻转所有位,所以0 - &gt; 1和1 - &gt; 0

        1111 1111 1111 1111  1111 1111 1111 1111 -> 0000 0000 0000 0000 0000 0000 0000 0000
        
      2. 在结果中添加一个。

        0000 0000 0000 0000 0000 0000 0000 0000 + 0001 = 0001
        
      3. 代表数字1.因此,我们发现1111 1111 1111 1111 1111 1111 1111 1111是-1的表示。