为什么i = i +我给我0?

Dea*_*Iss 96 java math variable-assignment

我有一个简单的程序:

public class Mathz {
    static int i = 1;
    public static void main(String[] args) {    
        while (true){
            i = i + i;
            System.out.println(i);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行这个程序,我看到的是0i我的输出.我原本预计会有第一次i = 1 + 1,然后是i = 2 + 2,然后是i = 4 + 4等等.

这是因为我们一旦尝试i在左侧重新声明,它的值会重置为0

如果有人能指出我更精细的细节,这将是伟大的.

更改intlong,似乎是按预期打印数字.我惊讶于它达到最大32位值的速度有多快!

Ali*_*ani 334

介绍

问题是整数溢出.如果它溢出,它会回到最小值并从那里继续.如果它下溢,它会回到最大值并从那里继续.下图是里程表.我用它来解释溢出.这是一个机械溢出,但仍然是一个很好的例子.

在里程表中,max digit = 9超出最大限度的手段9 + 1,它会带来并给出一个0; 但是没有更高的数字可以更改为a 1,因此计数器将重置为zero.你明白了 - 现在想到"整数溢出".

在此输入图像描述 在此输入图像描述

int类型的最大十进制文字是2147483647(2 31 -1).从0到2147483647的所有十进制文字都可能出现在int文字可能出现的任何地方,但文字2147483648可能只出现作为一元否定运算符的操作数 - .

如果整数加法溢出,则结果是数学和的低阶位,如某些足够大的二进制补码格式所示.如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同.

因此,2147483647 + 1溢出和包裹到-2147483648.因此int i=2147483647 + 1会溢出,这不等于2147483648.另外,你说"它总是打印0".它没有,因为http://ideone.com/WHrQIW.下面,这8个数字表示它转动和溢出的点.然后它开始打印0.此外,不要惊讶它的计算速度有多快,今天的机器很快.

268435456
536870912
1073741824
-2147483648
0
0
0
0
Run Code Online (Sandbox Code Playgroud)

为什么整数溢出"包裹"

原始PDF

  • 我已经添加了"Pacman"的动画用于符号目的,但它也可以看出人们如何看到"整数溢出". (17认同)
  • 这是我在这个网站上最喜欢的答案. (9认同)
  • 对于那些没有得到象征意义的人:https://en.wikipedia.org/wiki/Kill_screen#Pac-Man (3认同)
  • 你似乎错过了这是一个加倍的序列,而不是添加一个. (2认同)
  • 我认为pacman动画得到的回答比接受的回答更多.对我有另一个赞成 - 这是我最喜欢的游戏之一! (2认同)

Lou*_*man 168

问题是由于整数溢出.

在32位二进制补码算法中:

i确实开始具有两个幂的值,但是一旦你到达2 30,溢出行为就开始了:

2 30 + 2 30 = -2 31

-2 31 + -2 31 = 0

......在int算术中

  • 这个答案甚至没有完成(它甚至没有_mention_在最初的几次迭代中值将不是'0`,但是输出的速度从OP中掩盖了这个事实).为什么接受? (52认同)
  • 你能稍微扩展一下你的答案吗? (28认同)
  • @oOTesterOo它开始打印2,4等但它很快达到整数的最大值并且它"回绕"到负数,一旦它达到零,它永远保持在零 (17认同)
  • 据推测它被接受了,因为OP被认为是有帮助的. (16认同)
  • 没关系,这是我是一个白痴^^欢呼 (5认同)
  • @LightnessRacesinOrbit虽然它没有直接解决OP在他们的问题中提出的问题,但答案提供了足够的信息,一个体面的程序员应该能够推断出正在发生的事情. (4认同)

pet*_*rov 46

不,它不会只打印零.

将其更改为此,您将看到会发生什么.

    int k = 50;
    while (true){
        i = i + i;
        System.out.println(i);
        k--;
        if (k<0) break;
    }
Run Code Online (Sandbox Code Playgroud)

发生什么叫做溢出.

  • 有趣的方式写一个for循环:) (61认同)
  • 您可以使用隐藏运算符`while(k - > 0)`通俗地命名为"而`k`转到'0`";) (18认同)
  • @Bernhard这可能是为了保持OP程序的结构. (17认同)
  • 我只想补充一些陈述; 不删除/更改任何陈述.我很惊讶它引起了如此广泛的关注. (7认同)
  • @Taemyr可能,但他可以用`i <10000`替换`true` :) (4认同)

小智 15

static int i = 1;
    public static void main(String[] args) throws InterruptedException {
        while (true){
            i = i + i;
            System.out.println(i);
            Thread.sleep(100);
        }
    }
Run Code Online (Sandbox Code Playgroud)

出局:

2
4
8
16
32
64
...
1073741824
-2147483648
0
0

when sum > Integer.MAX_INT then assign i = 0;
Run Code Online (Sandbox Code Playgroud)

  • 嗯,不,它只适用于这个特定的序列才能达到零.尝试从3开始. (4认同)