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
介绍
问题是整数溢出。 如果它溢出,它会回到最小值并从那里继续。 如果它下溢,它会回到最大值并从那里继续。 下图是里程表。 我用它来解释溢出。 这是一个机械溢出,但仍然是一个很好的例子。
在里程表中, + 1,因此超出最大值意味着-,其中结转并给出int i= + 1; 但是没有更高的数字可以更改为,因此计数器将重置为zero。您明白了 - 现在可以想到“整数溢出”。
int类型的最大十进制文字是(231-1)。 所有 从0到的十进制文字可能出现在int的任何地方 文字可能会出现,但文字可能只出现 一否定算子的操作数 - 。
如果整数加法溢出,则结果为低位 数学和的位用一些足够大的数字表示 二进制补码格式。 如果发生溢出,则表示符号 结果与两者的数学和的符号不同 操作数值。
因此, + 1溢出并回绕到-。因此int i= + 1将溢出,这不等于.此外,您说“它总是打印0”。 它没有,因为[http://ideone.com/WHrQIW。]下面,这8个数字显示了它转动和溢出的点。 然后它开始打印0。 此外,不要惊讶它的计算速度有多快,今天的机器很快。
-
0
0
0
0
为什么整数溢出“包裹”
原始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
...
-
0
0
when sum > Integer.MAX_INT then assign i = 0;
TrungTran05T3 answered 2019-08-04T02:01:00Z
4 votes
由于我没有足够的声誉,我无法在带有受控输出的C中发布相同程序的输出图片,你可以尝试自己看看它实际上打印了32次然后由于溢出而解释i = + 改变为-还有一个进一步的加法超出了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次迭代后, + 无法正确计算,之后仅打印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开头并且将值加倍,直到它导致溢出。
user answered 2019-08-04T02:04:11Z
2 votes
我将使用8位数字进行说明,因为它可以在短空间内完全详细说明。 十六进制数字以0x开头,而二进制数字以0b开头。
8位无符号整数的最大值为255(0xFF或0b)。如果添加1,通常会得到:256(0x100或0b)。但由于那个位数太多(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 = 0b
64 = 0x40 = 0b
128 = 0x80 = 0b
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类型中最大的十进制文字是(= 231)。 从0到的所有十进制文字都可能出现在int文字可能出现的任何地方,但文字可能只出现作为一否定运算符的操作数 - 。
如果整数加法溢出,则结果是数学和的低阶位,如某些足够大的二进制补码格式所示。 如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同。
Scooba doo answered 2019-08-04T02:05:30Z
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/81557.html