对于 i 的什么值,而 (i == i + 1) {} 永远循环?
考虑以下循环,其中 i 到目前为止尚未声明:
while (i == i + 1) {}
找到此循环前面的 的定义,以便 while 循环永远持续下去。i
下一个问题,它对此代码片段提出了相同的问题:
while (i != i) {}
对我来说是显而易见的。当然,在另一种情况下,情况确实如此,但我真的被困在了前一种情况下。这与溢出有关吗?什么会导致这样的循环在Java中永远循环?NaN
考虑以下循环,其中 i 到目前为止尚未声明:
while (i == i + 1) {}
找到此循环前面的 的定义,以便 while 循环永远持续下去。i
下一个问题,它对此代码片段提出了相同的问题:
while (i != i) {}
对我来说是显而易见的。当然,在另一种情况下,情况确实如此,但我真的被困在了前一种情况下。这与溢出有关吗?什么会导致这样的循环在Java中永远循环?NaN
首先,由于循环不改变 的值,使此循环无限等价于选择满足的值。while (i == i + 1) {}
i
i
i == i + 1
有许多这样的值:
让我们从“异国情调”开始:
double i = Double.POSITIVE_INFINITY;
或
double i = Double.NEGATIVE_INFINITY;
这些值满足的原因在 JLS 15.18.2 中
说明。数值类型的加法运算符 (+ 和 -):i == i + 1
无穷大和有限值之和等于无限操作数。
这并不奇怪,因为将有限值添加到无限值应该产生无限值。
也就是说,该满足的大多数值只是大(或)值:i
i == i + 1
double
float
例如:
double i = Double.MAX_VALUE;
或
double i = 1000000000000000000.0;
或
float i = 1000000000000000000.0f;
和 类型的精度有限,因此,如果采用足够大的值,则向其添加将产生相同的值。double
float
double
float
1
这些谜题在Joshua Bloch和Neal Gafter的“Java Puzzlers: Traps, Pitfalls, and Corner Cases”一书中有详细描述。
double i = Double.POSITIVE_INFINITY;
while (i == i + 1) {}
艺术
double i = 1.0e40;
while (i == i + 1) {}
两者都将导致无限循环,因为添加到足够大的浮点值不会改变该值,因为它不会“弥合与其后继者1的差距”。1
关于第二个谜题的说明(供未来的读者使用):
double i = Double.NaN;
while (i != i) {}
还会导致无限循环,因为 NaN 不等于任何浮点值,包括其本身 2。
1 - Java益智游戏:陷阱、陷阱和角落案例(第4章 - Loopy Puzzlers)。
2 - JLS §15.21.1