英国の大学試験の上級プログラミングコースからこのパズルを渡って走りました 。
次のループを考えてみましょう。ここで、iは未だ宣言されていません。
while (i == i + 1) {}
このループの前にあるi
の定義を探します whileループは永遠に続くように
次の質問では、このコードスニペットについて同じ質問をしました。
while (i != i) {}
私には明白でした。もちろんこの他の状況ではそれはNaN
ですが、私は以前のものに本当にこだわっています。これはオーバーフローと関係がありますか? Javaでこのようなループがループし続ける原因は何でしょうか。
まず第一に、while (i == i + 1) {}
ループはi
の値を変更しないので、このループを無限にすることは、i == i + 1
を満たすi
の値を選択することと同じです。
そのような値はたくさんあります:
「エキゾチック」なものから始めましょう。
double i = Double.POSITIVE_INFINITY;
または
double i = Double.NEGATIVE_INFINITY;
これらの値がi == i + 1
を満たす理由は、
JLS 15.18.2。数値型の加算演算子(+と - ) :
無限大と有限値の合計は、無限オペランドと等しくなります。
無限値に有限値を加えると無限値になるはずなので、これは驚くことではありません。
とはいえ、i == i + 1
を満たすi
の値の大部分は、単に大きい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 Puzzlers:トラップ、落とし穴、コーナーケース(4章 - Loopy Puzzlers).
2 - JLS 15.21.1
double i = Double.POSITIVE_INFINITY;
ただのアイデア:ブール値はどうですか?
bool i = TRUE;
これはi + 1 == i
のケースではないでしょうか。