java i 0_java - 为什么i = i +我给我0?

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

我有一个简单的程序:

public class Mathz {

static int i = 1;

public static void main(String[] args) {

while (true){

i = i + i;

System.out.println(i);

}

}

}

当我运行这个程序时,我看到的只是int for long在我的输出中。 我原本预计第一轮会有i = 1 + 1,其次是i = 2 + 2,其次是i = 4 + 4等。

这是因为我们一旦尝试在左侧重新声明int,其值将重置为long吗?

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

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

10个解决方案

334 votes

介绍

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

在里程表中,2147483647 + 1,因此超出最大值意味着-2147483648,其中结转并给出int i=2147483647 + 1; 但是没有更高的数字可以更改为2147483648,因此计数器将重置为zero。您明白了 - 现在可以想到“整数溢出”。

fe06ea07138388893736282d0308c1b2.png

7cba79caf677bc6b3bb39487fd3cc492.gif

e7c70ff9726cfc7e3402b298a3096f52.png

int类型的最大十进制文字是2147483647(231-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

为什么整数溢出“包裹”

3415b51f21dbc1604b5c607ce2a696c1.png原始PDF

Ali Gajani answered 2019-08-04T01:59:52Z

168 votes

问题是由于整数溢出。

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

i确实开始具有二次幂值,但是一旦达到230,溢出行为就开始了:

230 + 230 = -231

-231 + -231 = 0

...在int算术。

Louis Wasserman answered 2019-08-04T01:58:38Z

46 votes

不,它不会只打印零。

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

int k = 50;

while (true){

i = i + i;

System.out.println(i);

k--;

if (k<0) break;

}

发生什么叫做溢出。

peter.petrov answered 2019-08-04T02:00:33Z

15 votes

static int i = 1;

public static void main(String[] args) throws InterruptedException {

while (true){

i = i + i;

System.out.println(i);

Thread.sleep(100);

}

}

出局:

2

4

8

16

32

64

...

1073741824

-2147483648

0

0

when sum > Integer.MAX_INT then assign i = 0;

TrungTran05T3 answered 2019-08-04T02:01:00Z

4 votes

由于我没有足够的声誉,我无法在带有受控输出的C中发布相同程序的输出图片,你可以尝试自己看看它实际上打印了32次然后由于溢出而解释i = 1073741824 + 1073741824 改变为-2147483648还有一个进一步的加法超出了int的范围并变为零。

#include

#include

int main()

{

static int i = 1;

while (true){

i = i + i;

printf("\n%d",i);

_getch();

}

return 0;

}

Kaify answered 2019-08-04T02:01:27Z

4 votes

i的值使用固定数量的二进制数字存储在存储器中。 当一个数字需要的数字多于可用数字时,只存储最低位数(最高位数会丢失)。

将00000000添加到自身与将i乘以2相同。 就像将数字乘以十进制表示法一样,可以通过向左滑动每个数字并在右边放置零来执行,以二进制表示法将数字乘以2可以以相同的方式执行。 这会在右侧添加一位数字,因此数字会在左侧丢失。

这里的起始值是1,所以如果我们使用8位数来存储00000000(例如),

在0次迭代之后,值为00000000

1次迭代后,值为00000000

经过2次迭代后,值为00000000

等等,直到最后的非零步

经过7次迭代后,值为00000000

经过8次迭代后,值为00000000

无论分配多少二进制数来存储数字,无论起始值是多少,最终所有数字都会丢失,因为它们被推向左边。 在那之后,继续加倍数字将不会改变数字 - 它仍将由全零表示。

starchild answered 2019-08-04T02:03:00Z

3 votes

这是正确的,但在31次迭代后,1073741824 + 1073741824无法正确计算,之后仅打印0。

您可以重构使用BigInteger,因此您的无限循环将正常工作。

public class Mathz {

static BigInteger i = new BigInteger("1");

public static void main(String[] args) {

while (true){

i = i.add(i);

System.out.println(i);

}

}

}

Bruno Volpato answered 2019-08-04T02:03:35Z

2 votes

为了调试这种情况,最好减少循环中的迭代次数。 使用此代替您的while(true):

for(int r = 0; r<100; r++)

然后,您可以看到它以2开头并且将值加倍,直到它导致溢出。

user3732069 answered 2019-08-04T02:04:11Z

2 votes

我将使用8位数字进行说明,因为它可以在短空间内完全详细说明。 十六进制数字以0x开头,而二进制数字以0b开头。

8位无符号整数的最大值为255(0xFF或0b11111111)。如果添加1,通常会得到:256(0x100或0b100000000)。但由于那个位数太多(9),超过了最大值,所以第一部分就会被删除,让你有效地为0(0x(1)00或0b(1)00000000,但是丢弃了1)。

所以,当你的程序运行时,你得到:

1 = 0x01 = 0b1

2 = 0x02 = 0b10

4 = 0x04 = 0b100

8 = 0x08 = 0b1000

16 = 0x10 = 0b10000

32 = 0x20 = 0b100000

64 = 0x40 = 0b1000000

128 = 0x80 = 0b10000000

256 = 0x00 = 0b00000000 (wraps to 0)

0 + 0 = 0 = 0x00 = 0b00000000

0 + 0 = 0 = 0x00 = 0b00000000

0 + 0 = 0 = 0x00 = 0b00000000

...

rich remer answered 2019-08-04T02:04:54Z

1 votes

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

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

Scooba doo answered 2019-08-04T02:05:30Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值