在审查考试时,我注意到我写了一个逻辑错误,我认为这是因为复合赋值+ =因为Increment ++按预期执行,但只有在将foo的值赋给foo +1时才会发生
foo += foo + 1;
Run Code Online (Sandbox Code Playgroud)
这是代码.
//Break Statement
Boolean exit = false;
int foo = 1, bar = 60;
while (!exit) {
foo+=foo+1; //Bad Code
//foo++; //Good Code
//foo=foo+1; // Good Code
//foo+=1; // Good Code
//System.out.println(foo); //Results in -1 (Infinite Loop)
if (foo == bar) {
break;
}
System.out.println("stuff");
}
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么foo + = foo + 1导致-1?
请注意:我是Stackoverflow的新手,无法对你的答案进行投票,所以知道我感谢任何帮助,并提前感谢你!
Jas*_*n C 13
如果你在谈论它在循环结束时为-1; 这只是因为int签名而且它已经结束了.
int foo = 1;
while (foo >= 0) {
foo += foo + 1;
}
System.out.println(foo);
Run Code Online (Sandbox Code Playgroud)
foo += 1 + 1 ---> 3
foo += 3 + 1 ---> 7
foo += 7 + 1 ---> 15
foo += 15 + 1 ---> 31
foo += 31 + 1 ---> 63
foo += 63 + 1 ---> 127
foo += 127 + 1 ---> 255
foo += 255 + 1 ---> 511
foo += 511 + 1 ---> 1023
foo += 1023 + 1 ---> 2047
foo += 2047 + 1 ---> 4095
foo += 4095 + 1 ---> 8191
foo += 8191 + 1 ---> 16383
foo += 16383 + 1 ---> 32767
foo += 32767 + 1 ---> 65535
foo += 65535 + 1 ---> 131071
foo += 131071 + 1 ---> 262143
foo += 262143 + 1 ---> 524287
foo += 524287 + 1 ---> 1048575
foo += 1048575 + 1 ---> 2097151
foo += 2097151 + 1 ---> 4194303
foo += 4194303 + 1 ---> 8388607
foo += 8388607 + 1 ---> 16777215
foo += 16777215 + 1 ---> 33554431
foo += 33554431 + 1 ---> 67108863
foo += 67108863 + 1 ---> 134217727
foo += 134217727 + 1 ---> 268435455
foo += 268435455 + 1 ---> 536870911
foo += 536870911 + 1 ---> 1073741823
foo += 1073741823 + 1 ---> 2147483647
foo += 2147483647 + 1 ---> -1
Run Code Online (Sandbox Code Playgroud)
数学运算就是这样.每次迭代都会产生比2的幂小1的值.我想如果你算出代数,你就可以证明这一点.因此有意义的是它会达到-1,在32位签名中int,它是2 32 -1.
然后,正如汤姆和托马斯·泽马精明地指出的那样,它会被卡住,因为-1 + -1 + 1它仍然只是-1.
还要注意,正如汤姆在下面的评论中发现的那样,无论你从哪个数字开始,你都会达到-1.这是因为foo += foo + 1它是相同的foo = 2 * foo + 1,实际上只是foo = (foo << 1) | 1(左移[导致低位0]然后导通低位 - 与数字为偶数时加1相同).因此,无论你从什么开始,在最多32次(或者有多少位)迭代之后,你最终会将你的起始值从左侧移开并用全部1替换它(以2的补码代替) signed int,是值-1).例如,带有签名的8位数:
abcdefgh starting foo, 8 unknown bits
bcdefgh0 add to itself (or multiply by two, or left shift)
bcdefgh1 add one
...
cdefgh11 again
defgh111 and again
efgh1111 and again
fgh11111 and again
gh111111 and again
h1111111 and again
11111111 and again, now it's -1
... and for completeness:
11111110 left shift -1
11111111 add 1, it's back to -1
Run Code Online (Sandbox Code Playgroud)
顺便说一下,无论你从哪个号码开始,你都不会达到60(或任何偶数,就此而言).你可以用一些快速代数来证明这一点:如果60 = 2*foo + 1,那么之前的foo = 59/2已经不是一个整数; 所以你永远不会有一个整数foo,使得60 = 2*foo + 1.
foo += foo + 1
Run Code Online (Sandbox Code Playgroud)
被解析为
foo = (foo) + (foo + 1)
Run Code Online (Sandbox Code Playgroud)
不 foo = (foo + 1)
意思是你得到
1: 3 (+ 1 + 2)
2: 7 (+3 + 4)
3: 15 (+7 +8)
4: 31 (+15 +16)
5: 63 (+32 +33)
Run Code Online (Sandbox Code Playgroud)
等等
所以你永远不会拥有foo == 60和无限循环.
eta:我似乎只是在学习一些东西.int翻转并命中-1.谢谢@Jason C.
| 归档时间: |
|
| 查看次数: |
289 次 |
| 最近记录: |