+0と-0は同じですか?


171

通読はECMAScript 5.1仕様+0および-0区別されます。

なぜ+0 === -0評価するのtrueですか?



6
ES2015では、+ 0 Object.isと-0を区別するために使用できることに注意してください
Benjamin Gruenbaum

JSのDavid Flanaganが最も信頼できるガイドであると引用:数値演算の結果が表現可能な最小の数値よりゼロに近い場合にアンダーフローが発生します。この場合、JavaScriptは0を返します。負の数からアンダーフローが発生した場合、JavaScriptは「負のゼロ」と呼ばれる特別な値を返します。
RBT

回答:


193

JavaScriptはIEEE 754標準を使用して数値を表します。ウィキペディアから:

符号付きゼロは、関連する符号付きのゼロです。通常の算術演算では、-0 = +0 = 0です。ただし、計算では、いくつかの数値表現で2つのゼロの存在が許可され、多くの場合、-0(負のゼロ)および+0(正のゼロ)で表されます。これは、整数の一部の符号付き数表現、およびほとんどの浮動小数点数表現で発生します。通常、数値0は+0としてエンコードされますが、+ 0または-0のいずれかで表すことができます。

浮動小数点演算のIEEE 754標準(現在、浮動小数点数をサポートするほとんどのコンピューターとプログラミング言語で使用されています)では、+ 0と-0の両方が必要です。ゼロは1 / −0 = −∞および1 / + 0 = +∞のように拡張された実数線のバリアントと見なすことができ、ゼロによる除算は±0 /±0および±∞/±∞に対してのみ未定義です。

記事には、さまざまな表現に関する詳細情報が含まれています。

これが、技術的には両方のゼロを区別する必要がある理由です。

ただし、+0 === -0true と評価されます。何故ですか (...) ?

この動作は、セクション11.9.6厳密な等値比較アルゴリズムで明示的に定義されています(強調は一部私のものです)。

とが値x === yである比較ではxtrueまたはfalseがy生成されます。。このような比較は次のように実行されます。

(...)

  • Type(x)が数値の場合、

    1. xがNaNの場合、falseを返します。
    2. yがNaNの場合、falseを返します。
    3. xがyと同じ数値の場合、trueを返します。
    4. xが+0でyが-0の場合、trueを返します。
    5. xが−0でyが+0の場合、trueを返します。
    6. falseを返します。

(...)

(同じことが+0 == -0btwにも当てはまります。)

これは、論理的に御馳走に思える+0-0同じよう。それ以外の場合は、コードでこれを考慮に入れる必要があり、私は個人的にはそれをしたくありません;)


注意:

ES2015では、新しい比較方法が導入されていObject.isます。Object.isとを明示的に区別-0+0ます。

Object.is(-0, +0); // false

15
確かに1/0 === Infinity; // true、そして1/-0 === -Infinity; // true
user113716 2011

48
だから、私たちは持っ1 === 1+0 === -01/+0 !== 1/-0ますが。なんて変なんだ!
Randomblue 2011

8
@ランダム:それは確かに+0 !== -0;)より良いと思います。それは本当に問題を引き起こす可能性があります。
Felix Kling

@FelixKling、または0 !== +0/ 0 !== -0、これも実際に問題を引き起こします!
Yanick Rochon、2014年

5
実際、この動作モデルは数学の計算を制限します。たとえば、関数1 / xの値は0で無限大ですが、0に近づくと、正側または負側から分離されます。前者の場合、結果は+ inf、後者の場合、-infです。
Agoston Horvath、2014年

19

@ user113716のコメントを見落としたので、これを回答として追加します。

これを行うことにより、-0をテストできます。

function isMinusZero(value) {
  return 1/value === -Infinity;
}

isMinusZero(0); // false
isMinusZero(-0); // true

6
おそらく== 0もチェックするはずですが、上記のisMinusZero(-1e-323)はtrueを返します!
Chris

1
@Chris、倍精度指数の制限はe±308であり、数値は非正規化形式でのみ表すことができ、実装が異なれば、それらをどこでサポートするかについても意見が異なります。重要なのは、一部の浮動小数点モードの一部のマシンでは、数値は-0非正規化数として表され、他のマシンでは非正規化数として表されます0.000000000000001e-308。そのような山車、とても楽しい
弱点2017

これは他の言語でも動作する可能性があります(Cでテストして動作します)
Mukul Kumar

11

+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に変換します。


ありがとう。したがって、ゼロを追加すると、私が遭遇した問題がどのように修正されるのか奇妙です。「他のすべてが失敗した場合は、ゼロを追加します。」人生のレッスン。
Microsis

Math.atan(y / x)でもこれに遭遇したばかりで、(おそらく驚くべきことに)正または負の無限 "y / x"を処理できますが、xが-0の場合に誤った答えが返されます。「x」を「(x + 0)」に置き換えると修正されます。
ジェイコブC.がモニカを復活させる

5

ではIEEE 754規格のJavaScriptの数値タイプを表すために使用される、記号は、(1が負の数を示す)ビットで表されます。

その結果、表現可能な各数値には、次のような負の値と正の値の両方が存在します。 0ます。

これが理由でもある-0し、+0存在しています。


3
2の補数も符号にビットを使用しますが、ゼロ(正)は1つだけです。
Felix Kling、2011

1
はい。ただし、2の補数では、負のビットも値の一部であるため、負のビットを設定すると、ゼロではなくなります。
Arnaud Le Blanc

3

元のタイトルに答える Are +0 and -0 the same?

brainslugs83(の回答のコメントでSpudley)JSの+0と-0が同じではない重要なケースを指摘-関数として実装:

var sign = function(x) {
    return 1 / x === 1 / Math.abs(x);
}

これにより、標準以外のMath.sign正しい符号+0と-0が返されます。


2

0には2つの可能な値(ビット表現)があります。これは一意ではありません。特に浮動小数点数では、これが発生する可能性があります。これは、浮動小数点数が実際には一種の数式として格納されるためです。

整数も別々の方法で格納できます。符号ビットを追加した数値を使用できるため、16ビットのスペースに、15ビットの整数値と符号ビットを格納できます。この表現では、値1000(16進数)と0000はどちらも0ですが、一方は+0、もう一方は-0です。

これは、-1から-2 ^ 16の範囲になるように整数値から1を減算することで回避できますが、これは不便です。

より一般的なアプローチは、整数を「2つの補数」に格納することですが、ECMAscriptはそうしないことを選択しました。この方法では、数値は0000から7FFFの正の範囲です。負の数はFFFF(-1)から8000までです。

もちろん、同じルールがより大きな整数にも適用されますが、Fを使い古したくありません。;)


4
しかし+0 === -0、少し変だとは思わないでしょう。なぜなら今、私たちは持っ1 === 1ている+0 === -01/+0 !== 1/-0...
Randomblue '28

2
もちろん+0は-0です。それはどちらでもありません。しかし、+ infinityと-infinityの間には大きな違いがありますか?これらの無限数は、ECMAが+0と-1の両方をサポートする理由である可能性さえあります。
GolezTrol 2011

+0 === -02つのビット表現が異なるにもかかわらず、理由を説明しません。
Randomblue 2011

1
+0は-0は0、何もない、nada、nienteです。それらが同じであることは理にかなっています。空が青いのはなぜですか?4 + 3も1 + 6と同じですが、表現は異なります。それらは異なる表現(したがって異なるビット値)を持っていますが、比較すると、それらは同じゼロとして処理されます。
GolezTrol 2011

1
彼らは同じではありません。それを示す例については、stackoverflow.com / questions / 7223717 / differentiating-0-and-0を参照してください。
Randomblue 2011

2

Object.is+0と-0、およびもう1つを区別するために使用できますNaN==NaN

Object.is(+0,-0) //false

Object.is(NaN,NaN) //true

1

厳密な平等比較法( '===')のせいだと思います。セクション4dを見てください。 ここに画像の説明を入力してください

仕様については、7.2.13厳密等価比較を参照してください。


0

ウィキペディアには、この現象を説明する優れた記事があります。 。http //en.wikipedia.org/wiki/Signed_zero

つまり、+ 0と-0の両方がIEEE浮動小数点仕様で定義されています。どちらも、技術的には符号なしの0(整数)とは区別されますが、実際にはすべて0と評価されるため、実用上、この区別は無視できます。


2
それは完全に正しいわけではありません-1 / -0 == 1/0は、たとえばJavaScriptではfalseと評価されます。このようIEEE 754の「符号なし整数ゼロ」とはそのような概念は存在しないため、彼らは、魔法の符号なしのゼロへの「評価」していない
BrainSlugs83
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.