Java 为什么 i = i + i 给我 0?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24173463/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does i = i + i give me 0?
提问by DeaIss
I have a simple program:
我有一个简单的程序:
public class Mathz {
static int i = 1;
public static void main(String[] args) {
while (true){
i = i + i;
System.out.println(i);
}
}
}
When I run this program, all I see is 0
for i
in my output. I would have expected the first time round we would have i = 1 + 1
, followed by i = 2 + 2
, followed by i = 4 + 4
etc.
当我运行这个程序,我看到的是0
对i
我的输出。我原以为我们会在第一轮比赛中出现i = 1 + 1
,然后是i = 2 + 2
,然后是i = 4 + 4
等等。
Is this due to the fact that as soon as we try to re-declare i
on the left hand-side, its value gets reset to 0
?
这是因为一旦我们尝试i
在左侧重新声明,它的值就会重置为0
?
If anyone can point me into the finer details of this that would be great.
如果有人能指出我更详细的细节,那就太好了。
Change the int
to long
and it seems to be printing numbers as expected. I'm surprised at how fast it hits the max 32-bit value!
更改int
为long
,它似乎按预期打印数字。我对它达到最大 32 位值的速度感到惊讶!
采纳答案by Louis Wasserman
The issue is due to integer overflow.
问题是由于整数溢出。
In 32-bit twos-complement arithmetic:
在 32 位二进制补码算法中:
i
does indeed start out having power-of-two values, but then overflow behaviors start once you get to 230:
i
确实开始时具有两个值的幂,但是一旦达到 2 30就会开始溢出行为:
230+ 230= -231
-231+ -231= 0
2 30+ 2 30= -2 31
-2 31+ -2 31= 0
...in int
arithmetic, since it's essentially arithmetic mod 2^32.
...在int
算术中,因为它本质上是算术模 2^32。
回答by peter.petrov
No, it does not print only zeros.
不,它不只打印零。
Change it to this and you will see what happens.
将其更改为此,您将看到会发生什么。
int k = 50;
while (true){
i = i + i;
System.out.println(i);
k--;
if (k<0) break;
}
What happens is called overflow.
发生的事情称为溢出。
回答by Bruno Volpato
It is correct, but after 31 iterations, 1073741824 + 1073741824 doesn't calculate correctly and after that prints only 0.
这是正确的,但经过 31 次迭代后,1073741824 + 1073741824 计算不正确,之后只打印 0。
You can refactor to use BigInteger, so your infinite loop will work correctly.
您可以重构以使用 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);
}
}
}
回答by Ali Gajani
Introduction
介绍
The problem is integer overflow. If it overflows, it goes back to the minimum value and continues from there. If it underflows, it goes back to the maximum value and continues from there. The image below is of an Odometer. I use this to explain overflows. It's a mechanical overflow but a good example still.
问题是整数溢出。如果它溢出,它会回到最小值并从那里继续。如果它下溢,它会回到最大值并从那里继续。下图是里程表。我用它来解释溢出。这是一个机械溢出,但仍然是一个很好的例子。
In an Odometer, the max digit = 9
, so going beyond the maximum means 9 + 1
, which carries over and gives a 0
; However there is no higher digit to change to a 1
, so the counter resets to zero
. You get the idea - "integer overflows" come to mind now.
在里程表中,max digit = 9
, 所以超越最大意味着9 + 1
,它延续并给出0
; 但是,没有更高的数字可以更改为 a 1
,因此计数器重置为zero
。你明白了 - 现在想到“整数溢出”。
The largest decimal literal of type int is 2147483647 (231-1). All decimal literals from 0 to 2147483647 may appear anywhere an int literal may appear, but the literal 2147483648 may appear only as the operand of the unary negation operator -.
If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.
int 类型的最大十进制文字是 2147483647 (2 31-1)。从 0 到 2147483647 的所有十进制文字都可以出现在 int 文字可能出现的任何地方,但文字 2147483648 只能作为一元否定运算符 - 的操作数出现。
如果整数加法溢出,则结果是数学和的低位,以某种足够大的二进制补码格式表示。如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同。
Thus, 2147483647 + 1
overflows and wraps around to -2147483648
. Hence int i=2147483647 + 1
would be overflowed, which isn't equal to 2147483648
. Also, you say "it always prints 0". It does not, because http://ideone.com/WHrQIW. Below, these 8 numbers show the point at which it pivots and overflows. It then starts to print 0s. Also, don't be surprised how fast it calculates, the machines of today are rapid.
因此,2147483647 + 1
溢出并环绕到-2147483648
。因此int i=2147483647 + 1
会溢出,这不等于2147483648
。另外,您说“它总是打印 0”。它没有,因为http://ideone.com/WHrQIW。下面,这 8 个数字显示了它旋转和溢出的点。然后它开始打印 0。另外,不要惊讶它的计算速度有多快,今天的机器速度很快。
268435456
536870912
1073741824
-2147483648
0
0
0
0
Why integer overflow "wraps around"
为什么整数溢出“环绕”
回答by user3732069
For debugging such cases it is good to reduce the number of iterations in the loop. Use this instead of your while(true)
:
对于调试这种情况,最好减少循环中的迭代次数。使用它而不是你的while(true)
:
for(int r = 0; r<100; r++)
You can then see that it starts with 2 and is doubling the value until it is causing an overflow.
然后,您可以看到它以 2 开头,并将值加倍,直到导致溢出。
回答by TrungTran05T3
static int i = 1;
public static void main(String[] args) throws InterruptedException {
while (true){
i = i + i;
System.out.println(i);
Thread.sleep(100);
}
}
out put:
输出:
2
4
8
16
32
64
...
1073741824
-2147483648
0
0
when sum > Integer.MAX_INT then assign i = 0;
回答by Scooba doo
The largest decimal literal of type int
is 2147483648(=231). All decimal literals from0 to 2147483647may appear anywhere an int literal may appear, but the literal 2147483648may appear only as the operand of the unary negation operator -.
类型的最大十进制文字int
是2147483648(=2 31)。从0 到 2147483647 的所有十进制文字都可以出现在 int 文字可能出现的任何地方,但文字2147483648只能作为一元否定运算符 - 的操作数出现。
If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.
如果整数加法溢出,则结果是数学和的低位,以某种足够大的二进制补码格式表示。如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同。
回答by Kaify
Since I don't have enough reputation I cannot post the picture of the output for the same program in C with controlled output, u can try yourself and see that it actually prints 32 times and then as explained due to overflow i=1073741824 + 1073741824changes to -2147483648and one more further addition is out of range of int and turns to Zero.
由于我没有足够的声誉,我无法使用受控输出在 C 中发布同一个程序的输出图片,您可以自己尝试一下,看看它实际上打印了 32 次,然后如解释由于溢出i=1073741824 + 1073741824更改为-2147483648并且另外一个添加超出了 int 的范围并变为Zero.
#include<stdio.h>
#include<conio.h>
int main()
{
static int i = 1;
while (true){
i = i + i;
printf("\n%d",i);
_getch();
}
return 0;
}
回答by starchild
The value of i
is stored in memory using a fixed quantity of binary digits. When a number needs more digits than are available, only the lowest digits are stored (the highest digits get lost).
的值i
使用固定数量的二进制数字存储在内存中。当一个号码需要的位数多于可用的位数时,只存储最低的位数(最高的位数会丢失)。
Adding i
to itself is the same as multiplying i
by two. Just like multiplying a number by ten in decimal notation can be performed by sliding each digit to the left and putting a zero on the right, multiplying a number by two in binary notation can be performed the same way. This adds one digit on the right, so a digit gets lost on the left.
添加i
到自身与乘以i
2相同。就像将十进制数乘以十可以通过向左滑动每个数字并在右侧放置零来执行一样,可以以相同的方式将数字乘以二进制数。这会在右侧增加一位数字,因此在左侧会丢失一位数字。
Here the starting value is 1, so if we use 8 digits to store i
(for example),
这里的起始值为1,所以如果我们用8位数字来存储i
(例如),
- after 0 iterations, the value is
00000001
- after 1 iteration , the value is
00000010
- after 2 iterations, the value is
00000100
- 0次迭代后,值为
00000001
- 1次迭代后,值为
00000010
- 2次迭代后,值为
00000100
and so on, until the final non-zero step
依此类推,直到最后的非零步骤
- after 7 iterations, the value is
10000000
- after 8 iterations, the value is
00000000
- 7次迭代后,值为
10000000
- 8次迭代后,值为
00000000
No matter how many binary digits are allocated to store the number, and no matter what the starting value is, eventually all of the digits will be lost as they are pushed off to the left. After that point, continuing to double the number will not change the number - it will still be represented by all zeroes.
无论分配了多少个二进制数字来存储数字,也无论起始值是什么,最终所有数字都会在向左推时丢失。在那之后,继续将数字加倍不会改变数字——它仍然会用全零表示。
回答by rich remer
I'll use an 8-bit number for illustration because it can be completely detailed in a short space. Hex numbers begin with 0x, while binary numbers begin with 0b.
我将使用一个 8 位数字进行说明,因为它可以在很短的空间中完整地详细说明。十六进制数以 0x 开头,而二进制数以 0b 开头。
The max value for an 8-bit unsigned integer is 255 (0xFF or 0b11111111). If you add 1, you would typically expect to get: 256 (0x100 or 0b100000000). But since that's too many bits (9), that's over the max, so the first part just gets dropped, leaving you with 0 effectively (0x(1)00 or 0b(1)00000000, but with the 1 dropped).
8 位无符号整数的最大值为 255(0xFF 或 0b11111111)。如果加 1,通常会得到:256(0x100 或 0b100000000)。但由于位数太多 (9),超过了最大值,所以第一部分会被丢弃,有效地留下 0(0x(1)00 或 0b(1)00000000,但 1 被丢弃)。
So when your program runs, you get:
所以当你的程序运行时,你会得到:
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
...