このforループは止まりますか?
for (var i=0; 1/i > 0; i++) {
}
もしそうなら、いつ、なぜですか?止まると言われましたが、理由はありませんでした。
更新
調査の一環として、内部で何が行われているのかをすべて説明する非常に長く詳細な記事を書きました-JavaScriptのNumber型について知っておくべきことは次のとおりです
Number.MAX_SAFE_INTEGER + 1。
このforループは止まりますか?
for (var i=0; 1/i > 0; i++) {
}
もしそうなら、いつ、なぜですか?止まると言われましたが、理由はありませんでした。
調査の一環として、内部で何が行われているのかをすべて説明する非常に長く詳細な記事を書きました-JavaScriptのNumber型について知っておくべきことは次のとおりです
Number.MAX_SAFE_INTEGER + 1。
回答:
(私はメタコンテンツのファンではありませんが、gotnullとle_mの回答はどちらも正しいと便利です。これらは元々、このコミュニティWikiが投稿された後に行われた編集でさらにそうです。このCWの元の動機これらの編集の結果として、ほとんどがなくなっていますが、それは有用なままなので、...記載されている執筆者は数人だけですが、他の多くのコミュニティメンバーが、折りたたまれて整理されたコメントで大いに助けてくれました。名前の単なるCWではありません。)
ループは、正しく実装されたJavaScriptエンジンでは停止しません。(エンジンのホスト環境はそれが無限であるため、最終的にそれを終了する可能性がありますが、それは別のことです。)
理由は次のとおりです。
最初iは0、1/i > 0isの場合、JavaScriptでは1/0is Infinity、and、およびtrueであるため、条件はtrue Infinity > 0です。
その後、iは増加し、長い間正の整数値として増加し続けます(さらに9,007,199,254,740,991反復)。これらすべてのケースで、1/iは残ります> 0(ただし、の値は最後に向かって非常に小さく1/iなります!)。そのため、ループはi、値に到達するループまで継続しますNumber.MAX_SAFE_INTEGER。
JavaScriptの数値は、IEEE-754倍精度2進浮動小数点数であり、かなりコンパクトな形式(64ビット)であり、高速な計算と広い範囲を提供します。これは、数値を符号ビット、11ビットの指数、および52ビットの仮数として格納することによって行われます(ただし、賢いため、実際には53ビットの精度になります)。これは2進数(基数2)の浮動小数点です。仮数(およびいくらかの賢さ)は値を与え、指数は数の大きさを与えます。
当然ながら、有効ビットが非常に多いため、すべての数値を保存できるわけではありません。ここ数1、及びフォーマットが格納することができることを1後の次の最大数、1 + 2 -52 ≈1.00000000000000022、その1 + 2×2の後の次の最高-52 ≈1.00000000000000044。
+ ------------------------------------------------- --------------符号ビット / + ------- + ---------------------------------------- --------------指数 / / | + ------------------------------------------------- +-仮数 / / | / | 0 01111111111 0000000000000000000000000000000000000000000000000000 = 1 0 01111111111 0000000000000000000000000000000000000000000000000000000001 ≈1.00000000000000022 0 01111111111 0000000000000000000000000000000000000000000000000010 ≈1.00000000000000044
1.00000000000000022から1.00000000000000044へのジャンプに注意してください。1.0000000000000003を保存する方法はありません。これは整数でも発生する可能性があります。Number.MAX_SAFE_INTEGER(9,007,199,254,740,991)は、形式が保持できる正の最大整数値でiありi + 1、両方とも正確に表現できます(spec)。9,007,199,254,740,991と9,007,199,254,740,992の両方を表すことができますが、次の整数9,007,199,254,740,993は表すことができません。9,007,199,254,740,992の後に表すことができる次の整数は9,007,199,254,740,994です。以下はビットパターンです。右端(最下位)のビットに注意してください。
+ ------------------------------------------------- --------------符号ビット / + ------- + ---------------------------------------- --------------指数 / / | + ------------------------------------------------- +-仮数 / / | / | 0 10000110011 1111111111111111111111111111111111111111111111111111 = 9007199254740991(Number.MAX_SAFE_INTEGER) 0 10000110100 0000000000000000000000000000000000000000000000000000 = 9007199254740992(Number.MAX_SAFE_INTEGER + 1) x xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 9007199254740993(Number.MAX_SAFE_INTEGER + 2)は保存できません 0 10000110100 0000000000000000000000000000000000000000000000000000000001 = 9007199254740994(Number.MAX_SAFE_INTEGER + 3)
形式は基数2であり、その指数を使用すると、最下位ビットは小数ではなくなります。値は2です。オフ(9,007,199,254,740,992)またはオン(9,007,199,254,740,994)にすることができます。そのため、この時点で、整数(整数)スケールでも精度が失われ始めています。これはループに影響を与えます!
i = 9,007,199,254,740,992ループが完了したら、再びi++...を与えますi = 9,007,199,254,740,992。i次の整数は格納できず、計算結果は切り捨てられるため、に変化はありません。i変更すると変更されますがi += 2、i++変更できません。したがって、定常状態に到達しました。i決して変化せず、ループが終了することはありません。
関連するさまざまな計算を以下に示します。
if (!Number.MAX_SAFE_INTEGER) {
// Browser doesn't have the Number.MAX_SAFE_INTEGER
// property; shim it. Should use Object.defineProperty
// but hey, maybe it's so old it doesn't have that either
Number.MAX_SAFE_INTEGER = 9007199254740991;
}
var i = 0;
console.log(i, 1/i, 1/i > 0); // 0, Infinity, true
i++;
console.log(i, 1/i, 1/i > 0); // 1, 1, true
// ...eventually i is incremented all the way to Number.MAX_SAFE_INTEGER
i = Number.MAX_SAFE_INTEGER;
console.log(i, 1/i, 1/i > 0); // 9007199254740991 1.1102230246251568e-16, true
i++;
console.log(i, 1/i, 1/i > 0); // 9007199254740992 1.1102230246251565e-16, true
i++;
console.log(i, 1/i, 1/i > 0); // 9007199254740992 1.1102230246251565e-16, true (no change)
console.log(i == i + 1); // true
条件1/i > 0は常にtrueと評価されます。
最初はそれが理由本当だ1/0評価さにInfinityし、Infinity > 0真であります
以来、それは真のまま1/i > 0、すべてのために真であるi < Infinityとi++達することはありませんInfinity。
なぜi++到達しないのInfinityですか?Numberデータ型の精度に制限があるため、次のような値がありi + 1 == iます。
9007199254740992 + 1 == 9007199254740992 // true
一度i値が(に相当することに達する)、それも後に同じままになります。Number.MAX_SAFE_INTEGER + 1i++
したがって、無限ループがあります。
なんで9007199254740992 + 1 == 9007199254740992?
JavaScriptのNumberデータ型は、実際には64ビットのIEEE 754倍精度浮動小数点です。それぞれNumberは、3つの部分(1ビットの符号、11ビットの指数、52ビットの仮数)として分解されて格納されます。その値は-1 符号 ×仮数×2 指数です。
9007199254740992はどのように表されますか?1.0×2 53、またはバイナリで:

仮数の最下位ビットをインクリメントすると、次に大きい数が得られます。

その数の値は1.00000000000000022…×2 53 = 9007199254740994です
どういう意味ですか?Number900719925474099 2または900719925474099 4のいずれかになりますが、間には何もありません。
さて、900719925474099 2 + 1を表すためにどれを選択しますか?IEEE 754丸め規則は 900719925474099:答え与える2。
for (var i = 0; i < Infinity; i += 1E306);。たとえば、1よりはるかに大きい数だけインクリメントする必要があります。しかし、私はあなたがどこから来たのかを
このNumber.MAX_SAFE_INTEGER定数は、JavaScriptでの最大安全整数を表します。MAX_SAFE_INTEGER定数は、の値を持ちます9007199254740991。その数値の背後にある理由は、JavaScript がIEEE 754で指定されている倍精度浮動小数点形式の数値を使用し、-(2 53-1)と2 53-1の間の数値のみを安全に表すことができるためです。
この文脈での安全とは、整数を正確に表し、それらを正しく比較する機能を指します。たとえば、Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2はに評価されますがtrue、これは数学的に正しくありません。詳細についてはNumber.isSafeInteger()、を参照してください。
MAX_SAFE_INTEGERはの静的プロパティであるため、作成したオブジェクトのプロパティNumberとしてNumber.MAX_SAFE_INTEGERではなく、常にとして使用しNumberます。
更新:
削除された回答の誰かが言及しました:i無限に達することは決してありません。に達するNumber.MAX_SAFE_INTEGERとi++、変数をインクリメントしなくなります。これは実際には正しくありません。
@TJクラウダーは、コメントi = Number.MAX_SAFE_INTEGER; i++; i == Number.MAX_SAFE_INTEGER;ですfalse。しかし、次の反復は不変の状態に到達するため、mainの答えは正しいです。
i例では決して到達しませんInfinity。
9007199254740992 + 1は9007199254740992です。
for (var i=0; NaN > 0; i++) { console.log(i); }は何も生成しません。
1/i > 0)場合以来、偽だろうiである0、1/iあるNaN、とNaN > 0falseです。