通読はECMAScript 5.1仕様、+0
および-0
区別されます。
なぜ+0 === -0
評価するのtrue
ですか?
Object.is
と-0を区別するために使用できることに注意してください
通読はECMAScript 5.1仕様、+0
および-0
区別されます。
なぜ+0 === -0
評価するのtrue
ですか?
Object.is
と-0を区別するために使用できることに注意してください
回答:
JavaScriptはIEEE 754標準を使用して数値を表します。ウィキペディアから:
符号付きゼロは、関連する符号付きのゼロです。通常の算術演算では、-0 = +0 = 0です。ただし、計算では、いくつかの数値表現で2つのゼロの存在が許可され、多くの場合、-0(負のゼロ)および+0(正のゼロ)で表されます。これは、整数の一部の符号付き数表現、およびほとんどの浮動小数点数表現で発生します。通常、数値0は+0としてエンコードされますが、+ 0または-0のいずれかで表すことができます。
浮動小数点演算のIEEE 754標準(現在、浮動小数点数をサポートするほとんどのコンピューターとプログラミング言語で使用されています)では、+ 0と-0の両方が必要です。ゼロは1 / −0 = −∞および1 / + 0 = +∞のように拡張された実数線のバリアントと見なすことができ、ゼロによる除算は±0 /±0および±∞/±∞に対してのみ未定義です。
記事には、さまざまな表現に関する詳細情報が含まれています。
これが、技術的には両方のゼロを区別する必要がある理由です。
ただし、
+0 === -0
true と評価されます。何故ですか (...) ?
この動作は、セクション11.9.6の厳密な等値比較アルゴリズムで明示的に定義されています(強調は一部私のものです)。
とが値
x === y
である比較ではx
、trueまたはfalseがy
生成されます。。このような比較は次のように実行されます。(...)
Type(x)が数値の場合、
- xがNaNの場合、falseを返します。
- yがNaNの場合、falseを返します。
- xがyと同じ数値の場合、trueを返します。
- xが+0でyが-0の場合、trueを返します。
- xが−0でyが+0の場合、trueを返します。
- falseを返します。
(...)
(同じことが+0 == -0
btwにも当てはまります。)
これは、論理的に御馳走に思える+0
と-0
同じよう。それ以外の場合は、コードでこれを考慮に入れる必要があり、私は個人的にはそれをしたくありません;)
注意:
ES2015では、新しい比較方法が導入されていObject.is
ます。Object.is
とを明示的に区別-0
し+0
ます。
Object.is(-0, +0); // false
1/0 === Infinity; // true
、そして1/-0 === -Infinity; // true
。
1 === 1
て+0 === -0
い1/+0 !== 1/-0
ますが。なんて変なんだ!
+0 !== -0
;)より良いと思います。それは本当に問題を引き起こす可能性があります。
0 !== +0
/ 0 !== -0
、これも実際に問題を引き起こします!
@ user113716のコメントを見落としたので、これを回答として追加します。
これを行うことにより、-0をテストできます。
function isMinusZero(value) {
return 1/value === -Infinity;
}
isMinusZero(0); // false
isMinusZero(-0); // true
e±308
であり、数値は非正規化形式でのみ表すことができ、実装が異なれば、それらをどこでサポートするかについても意見が異なります。重要なのは、一部の浮動小数点モードの一部のマシンでは、数値は-0
非正規化数として表され、他のマシンでは非正規化数として表されます0.000000000000001e-308
。そのような山車、とても楽しい
+0と-0の動作がまったく異なる例を見つけました。
Math.atan2(0, 0); //returns 0
Math.atan2(0, -0); //returns Pi
注意:-0.0001のような負の数値でMath.roundを使用する場合でも、実際には-0になり、上記のように後続の計算を台無しにする可能性があります。
これをすばやく簡単に修正するには、次のようにします。
if (x==0) x=0;
あるいは単に:
x+=0;
これは、それが-0だった場合に番号を+0に変換します。
ではIEEE 754規格のJavaScriptの数値タイプを表すために使用される、記号は、(1が負の数を示す)ビットで表されます。
その結果、表現可能な各数値には、次のような負の値と正の値の両方が存在します。 0
ます。
これが理由でもある-0
し、+0
存在しています。
0には2つの可能な値(ビット表現)があります。これは一意ではありません。特に浮動小数点数では、これが発生する可能性があります。これは、浮動小数点数が実際には一種の数式として格納されるためです。
整数も別々の方法で格納できます。符号ビットを追加した数値を使用できるため、16ビットのスペースに、15ビットの整数値と符号ビットを格納できます。この表現では、値1000(16進数)と0000はどちらも0ですが、一方は+0、もう一方は-0です。
これは、-1から-2 ^ 16の範囲になるように整数値から1を減算することで回避できますが、これは不便です。
より一般的なアプローチは、整数を「2つの補数」に格納することですが、ECMAscriptはそうしないことを選択しました。この方法では、数値は0000から7FFFの正の範囲です。負の数はFFFF(-1)から8000までです。
もちろん、同じルールがより大きな整数にも適用されますが、Fを使い古したくありません。;)
+0 === -0
、少し変だとは思わないでしょう。なぜなら今、私たちは持っ1 === 1
ている+0 === -0
が1/+0 !== 1/-0
...
+0 === -0
2つのビット表現が異なるにもかかわらず、理由を説明しません。
ウィキペディアには、この現象を説明する優れた記事があります。 。http //en.wikipedia.org/wiki/Signed_zero
つまり、+ 0と-0の両方がIEEE浮動小数点仕様で定義されています。どちらも、技術的には符号なしの0(整数)とは区別されますが、実際にはすべて0と評価されるため、実用上、この区別は無視できます。