web-dev-qa-db-ja.com

(i == i + 1){}が永遠にループしている間に、iの値は何をしますか?

英国の大学試験の上級プログラミングコースからこのパズルを渡って走りました

次のループを考えてみましょう。ここで、iは未だ宣言されていません。

while (i == i + 1) {}

このループの前にあるiの定義を探します whileループは永遠に続くように

次の質問では、このコードスニペットについて同じ質問をしました。

while (i != i) {}

私には明白でした。もちろんこの他の状況ではそれはNaNですが、私は以前のものに本当にこだわっています。これはオーバーフローと関係がありますか? Javaでこのようなループがループし続ける原因は何でしょうか。

117
jake mckenzie

まず第一に、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を追加すると同じ値になります。

141
Eran

これらのパズルについては、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

64
Oleksandr

double i = Double.POSITIVE_INFINITY;

1
Farcas George

ただのアイデア:ブール値はどうですか?

bool i = TRUE;

これはi + 1 == iのケースではないでしょうか。

1
Dominique