2015-11-04 8 views
8

特にダブルカウンタが(2-2^-52)・2^1023に達すると、次のコードはどのように振る舞いますか?forループ(Java)のDouble.POSITIVE_INFINITYの使用

for (double i = 0; i < Double.POSITIVE_INFINITY; i++){ 
    //do something 
} 

このコードは、予想(ループ永遠に)またはいくつかの点で失敗するように動作し、なぜでしょうか?

ありがとうございました。

+0

私はそれがその価値になるという保証はないと主張したいと思います。二重算術の振る舞いのために、その値に達する前に「私」がアンダーフローしないと誰が言いますか? – Makoto

+0

なぜそれを試してみませんか? – Grodriguez

+0

@Makotoそれは基本的に私が求めていることです。興味深いのはエッジケースだけです。 – Samir

答えて

5

を印刷します。

この理由は十分に大きいdouble番号に1を追加すると、その値を変更しないということです。実際には

double a = 1.7976931348623155E308; 
double old = a; 
a++; 
System.out.println(a);  // prints 1.7976931348623155E308 
System.out.println(old); // prints 1.7976931348623155E308 
System.out.println(a==old); // prints "true" 

Demo.

doubleの値が正の無限大に十分に近づいたとき、大きな二重の変更値を作成してPOSITIVE_INFINITYにするためには、1よりも上の数値を追加する必要があります。

この理由は、doubleが大きな数を表すためです。数値の最上位桁を表すために短いの仮数を使用し、小数点の配置先を示す指数を使用します。非常に大きい数の場合、指数は、本質的に、仮数のバイナリ表現の後にいくつのゼロを追加する必要があるかを示すものです。

doubleを追加して数値を変更するには、少なくとも仮数の最下位ビットと同じ大きさの数値を追加する必要があります。バイナリ指数が48を超えると、結果が異なるために追加する必要がある最小の数は2になります。つまり、++は値を変更しなくなります。

+0

完全に0の効果がありますか?ビットやメモリの変更はありませんか?それとも、多数の人の後に効果がありますか? 「十分に大きい」とは、正確にはどういう意味ですか? – Samir

+2

@Samir大きな数値に1を加えることは効果がありません。浮動小数点ユニットは、加算される2つの数値の指数が交差しない範囲に仮数部を置くことを認識すると、ユニットは停止し、大きな数値の値を返します。 – dasblinkenlight

6

i++は、非常に大きな値のiの場合、連続するdoubleの値が離れているため、何らかの影響がなくなることがあります。

したがって、無限ループです。これを試してi == i + 1ためdouble値があることを証明する

for (double i = 1;; i *= 2){ 
    if (i == i + 1) { 
     System.out.println(i); 
     break; 
    } 
} 

それは、このコードは、ループを終了することはありません

9.007199254740992E15 
+0

それは面白いです、それを知らなかった。増分が永遠に効果を失うか、変化を見るのに本当に長い時間がかかりますか?また、カウンターはこのループでオーバーフローしますか? – Samir

+2

@サミールそれは今まで効果がありません。それはどこかの増加を "秘密に"保っているわけではありません。 ''私は十分に大きくなると、全く変化はありません。 'i'がその値に達すると、それは完全に変化します_。 –

+0

@Samir浮動小数点値に無限の解像度がありません。https://en.wikipedia.org/wiki/Unit_in_the_last_placeは、必要最小限の「ステップ」です。この時点では1より大きい – zapl