jak*_*zie 118 java types loops
考虑以下循环,到目前为止,我是未声明的:
while (i == i + 1) {}
Run Code Online (Sandbox Code Playgroud)
找到i
在此循环之前的定义,以便while循环永远持续.
下一个问题,为此代码片段提出了同样的问题:
while (i != i) {}
Run Code Online (Sandbox Code Playgroud)
对我来说很明显.当然,在另一种情况下,NaN
我确实陷入了前一个问题.这与溢出有关吗?什么会导致这样的循环在Java中永远循环?
Era*_*ran 141
首先,由于while (i == i + 1) {}
循环不会改变值i
,因此使该循环无限等同于选择i
满足的值i == i + 1
.
有很多这样的价值观:
让我们从"异国情调"开始吧:
double i = Double.POSITIVE_INFINITY;
Run Code Online (Sandbox Code Playgroud)
要么
double i = Double.NEGATIVE_INFINITY;
Run Code Online (Sandbox Code Playgroud)
这些值满足的原因i == i + 1
在
JLS 15.18.2中说明.数值类型的加法运算符(+和 - ):
无穷大和有限值之和等于无穷操作数.
这并不奇怪,因为将有限值添加到无限值应该会产生无限值.
也就是说i
,满足的大多数值i == i + 1
都只是大double
(或float
)值:
例如:
double i = Double.MAX_VALUE;
Run Code Online (Sandbox Code Playgroud)
要么
double i = 1000000000000000000.0;
Run Code Online (Sandbox Code Playgroud)
要么
float i = 1000000000000000000.0f;
Run Code Online (Sandbox Code Playgroud)
在double
和float
类型已经精度有限,因此,如果你把一个足够大double
或float
价值,加上1
它会导致相同的值.
Ole*_*hov 64
这些谜题在Joshua Bloch和Neal Gafter的"Java Puzzlers:陷阱,陷阱和角落案例"一书中有详细描述.
double i = Double.POSITIVE_INFINITY;
while (i == i + 1) {}
Run Code Online (Sandbox Code Playgroud)
要么:
double i = 1.0e40;
while (i == i + 1) {}
Run Code Online (Sandbox Code Playgroud)
两者都会导致无限循环,因为添加1
到足够大的浮点值不会改变该值,因为它不会"缩小"与其后继者之间的差距1.
关于第二个谜题(未来读者)的说明:
double i = Double.NaN;
while (i != i) {}
Run Code Online (Sandbox Code Playgroud)
也导致无限循环,因为NaN不等于任何浮点值,包括自身2.
1 - Java Puzzlers:陷阱,陷阱和角落案例(第4章 - Loopy Puzzlers).
2 - JLS§15.21.1