क्या +0 और -0 समान हैं?


171

ECMAScript 5.1 विनिर्देशन के माध्यम से पढ़ना , +0और -0प्रतिष्ठित हैं।

फिर +0 === -0मूल्यांकन क्यों करता है true?



6
ध्यान दें कि ES2015 में आप Object.is+0 और -0 को भेद करने के लिए उपयोग कर सकते हैं
बेंजामिन ग्रुएनबाम

जेएस से डेविड फ्लैगन को उद्धृत करते हुए निश्चित गाइड : अंडरफ्लो तब होता है जब एक संख्यात्मक ऑपरेशन का परिणाम सबसे छोटी प्रतिनिधित्व योग्य संख्या की तुलना में शून्य के करीब होता है। इस स्थिति में, जावास्क्रिप्ट 0. लौटाता है। यदि नकारात्मक संख्या से अंडरफ्लो होता है, तो जावास्क्रिप्ट एक विशेष मान लौटाता है जिसे "नकारात्मक शून्य" के रूप में जाना जाता है।
RBT

जवाबों:


193

जावास्क्रिप्ट संख्याओं का प्रतिनिधित्व करने के लिए IEEE 754 मानक का उपयोग करता है । से विकिपीडिया :

हस्ताक्षरित शून्य एक संबद्ध चिह्न के साथ शून्य है। साधारण अंकगणित में, −0 = +0 = 0. हालांकि, कंप्यूटिंग में, कुछ संख्या प्रतिनिधित्व दो शून्य के अस्तित्व की अनुमति देते हैं, जिन्हें अक्सर (0 (नकारात्मक शून्य) और +0 (सकारात्मक शून्य) द्वारा निरूपित किया जाता है । यह पूर्णांक के लिए कुछ हस्ताक्षरित संख्या प्रतिनिधित्वों में होता है, और अधिकांश अस्थायी बिंदु संख्या प्रतिनिधित्वों में। संख्या 0 को आमतौर पर +0 के रूप में एन्कोड किया जाता है, लेकिन इसे +0 या enc0 द्वारा दर्शाया जा सकता है।

अस्थायी बिंदु अंकगणित के लिए IEEE 754 मानक (वर्तमान में अधिकांश कंप्यूटर और प्रोग्रामिंग भाषा जो फ्लोटिंग पॉइंट संख्या का समर्थन करते हैं) का उपयोग करने के लिए +0 और −0 दोनों की आवश्यकता होती है। शून्य को विस्तारित वास्तविक संख्या रेखा के एक प्रकार के रूप में माना जा सकता है जैसे कि 1 / =0 = −∞ और 1 / + 0 = + be, शून्य से विभाजन केवल / 0 / ± 0 और be / ± be के लिए अपरिभाषित है। ।

लेख में विभिन्न अभ्यावेदन के बारे में अधिक जानकारी है।

यही कारण है कि, तकनीकी रूप से, दोनों शून्य को अलग करना होगा।

हालांकि, +0 === -0सच का मूल्यांकन करता है। ऐसा क्यों है (...) ?

यह व्यवहार स्पष्ट रूप से धारा 11.9.6 , सख्त समानता तुलनात्मक एल्गोरिथम (आंशिक रूप से मेरा जोर) में परिभाषित किया गया है :

तुलना x === y, जहां xऔर yमान हैं, सही या गलत पैदा करता है । इस तरह की तुलना इस प्रकार की जाती है:

(...)

  • यदि टाइप (x) संख्या है, तो

    1. यदि x NaN है, तो गलत लौटें।
    2. यदि y NaN है, तो गलत लौटें।
    3. यदि x y के समान संख्या मान है, तो सही लौटें।
    4. यदि x +0 है और y ,0 है, तो सही लौटें।
    5. यदि x true0 है और y +0 है, तो सही लौटें।
    6. विवरण झूठा है।

(...)

(वही जो +0 == -0btw के लिए रखती है ।)

यह व्यवहारिक रूप से +0और -0समान के रूप में लगता है । अन्यथा हमें अपने कोड में इसे ध्यान में रखना होगा और मैं, व्यक्तिगत रूप से, ऐसा नहीं करना चाहता;)


ध्यान दें:

ES2015 एक नई तुलना विधि का परिचय देता है Object.isObject.isस्पष्ट रूप से -0और के बीच अंतर करता है +0:

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

15
वास्तव में 1/0 === Infinity; // trueऔर 1/-0 === -Infinity; // true
user113716

48
तो हमारे पास है 1 === 1और +0 === -0लेकिन 1/+0 !== 1/-0। कितना अजीब है!
Randomblue

8
@ आयामी: मुझे लगता है कि यह निश्चित रूप से बेहतर है +0 !== -0;) जो वास्तव में समस्याएं पैदा कर सकता है।
फेलिक्स क्लिंग

@FelixKling, या 0 !== +0/ 0 !== -0, जो वास्तव में समस्याएं भी पैदा करेगा!
यानिक रोचोन

5
दरअसल, यह व्यवहार मॉडल गणित में गणना को सीमित करता है। उदाहरण के लिए फ़ंक्शन 1 / x में 0 में एक मान अनंत है, हालांकि, यह अलग हो जाता है अगर हम नकारात्मक पक्ष के सकारात्मक से 0 के करीब पहुंच रहे हैं; पूर्व में, परिणाम उत्तरार्द्ध में + inf है।
अगस्टोन होर्वाथ

19

मैं इसे एक उत्तर के रूप में जोड़ूंगा क्योंकि मैंने @ user113716 की टिप्पणी को अनदेखा कर दिया था।

आप ऐसा करके -0 का परीक्षण कर सकते हैं:

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

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

6
शायद == 0 के लिए भी जाँच करें, उपरोक्त isMinusZero (-1e-323) सही है!
क्रिस

1
@ क्रिस, डबल सटीक घातांक की सीमा है e±308, आपके नंबर का निरूपण केवल निरूपित रूप में किया जा सकता है और अलग-अलग क्रियान्वयन के बारे में अलग-अलग राय है कि उनका समर्थन कहां करना है या नहीं। बिंदु यह है कि, कुछ फ़्लोटिंग पॉइंट मोड्स की कुछ मशीनों पर आपके नंबर का प्रतिनिधित्व किया जाता है -0और दूसरों के रूप में इसे असमान संख्या के रूप में दर्शाया जाता है 0.000000000000001e-308। इस तरह की झांकियां, इतना मजेदार
8

यह अन्य भाषाओं के लिए भी काम कर सकता है (मैंने सी और इस काम के लिए परीक्षण किया)
मुकुल कुमार

11

मैं अभी एक उदाहरण भर में आया हूं, जहां +0 और -0 वास्तव में बहुत अलग व्यवहार करते हैं:

Math.atan2(0, 0);  //returns 0
Math.atan2(0, -0); //returns Pi

सावधान रहें: यहां तक ​​कि -0.001 जैसे एक नकारात्मक संख्या पर Math.round का उपयोग करते समय, यह वास्तव में -0 होगा और ऊपर दिखाए गए अनुसार कुछ बाद की गणनाओं को खराब कर सकता है।

इसे ठीक करने का त्वरित और गंदा तरीका है:

if (x==0) x=0;

या केवल:

x+=0;

यह -0 होने की स्थिति में संख्या को +0 में परिवर्तित करता है।


धन्यवाद। इतना अजीब है कि शून्य को जोड़ने से मैं जिस समस्या में भाग गया था उसे ठीक कर दूंगा। "यदि अन्य सभी विफल हो जाते हैं, तो शून्य जोड़ें।" जीवन के लिए एक सबक।
माइक्रोसिस्ट

मैंने इसे केवल Math.atan (y / x) के रूप में अच्छी तरह से सामना किया, जो (शायद आश्चर्यजनक रूप से) सकारात्मक या नकारात्मक रूप से अनंत "y / x" को संभाल सकता है, सिवाय इसके कि मामले में गलत जवाब देता है जहां x -0 है। "X" को "(x + 0)" से बदलकर "" ठीक करता है।
जैकब सी। कहते हैं, मोनिका

5

में आईईईई 754 मानक जावास्क्रिप्ट में संख्या प्रकार का प्रतिनिधित्व करते थे, संकेत एक सा का प्रतिनिधित्व करती है (एक 1 ऋणात्मक संख्या यह दर्शाती)।

नतीजतन, प्रत्येक प्रतिनिधित्व योग्य संख्या के लिए एक नकारात्मक और एक सकारात्मक मूल्य दोनों मौजूद हैं, जिसमें शामिल हैं 0

यही कारण है कि दोनों है -0और +0अस्तित्व।


3
दो के पूरक भी संकेत के लिए थोड़ा उपयोग करते हैं, लेकिन केवल एक शून्य (सकारात्मक) है।
फेलिक्स क्लिंग

1
हां, लेकिन दो के पूरक में ऋणात्मक-बिट भी मूल्य का हिस्सा है, इसलिए एक बार जब आप नकारात्मक-बिट सेट करते हैं, तो यह अब शून्य नहीं है।
अरनौद ले ब्लैंक

3

मूल शीर्षक का उत्तर देना Are +0 and -0 the same?:

brainslugs83(द्वारा जवाब की टिप्पणियों में Spudley) ने एक महत्वपूर्ण मामला बताया जिसमें जेएस में +0 और -0 समान नहीं हैं - फ़ंक्शन के रूप में लागू किया गया है:

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

यह, मानक Math.signके अलावा +0 और -0 का सही संकेत देता है।


2

0. के लिए दो संभावित मान (बिट प्रतिनिधित्व) हैं यह अद्वितीय नहीं है। विशेष रूप से फ्लोटिंग पॉइंट संख्या में यह हो सकता है। ऐसा इसलिए है क्योंकि फ्लोटिंग पॉइंट नंबर वास्तव में एक तरह के फॉर्मूले के रूप में संग्रहीत होते हैं।

इंटेगर को अलग-अलग तरीकों से भी संग्रहीत किया जा सकता है। आपके पास अतिरिक्त साइन-बिट के साथ संख्यात्मक मान हो सकता है, इसलिए 16 बिट स्थान में, आप 15 बिट पूर्णांक मान और साइन-बिट संग्रहीत कर सकते हैं। इस प्रतिनिधित्व में, मूल्य 1000 (हेक्स) और 0000 दोनों 0 हैं, लेकिन उनमें से एक +0 है और दूसरा -0 है।

इसे पूर्णांक मान से घटाकर 1 से घटाया जा सकता है, इसलिए यह -1 से -2 ^ 16 तक था, लेकिन यह असुविधाजनक होगा।

एक अधिक सामान्य दृष्टिकोण पूर्णांक को 'दो संकलन' में संग्रहीत करना है, लेकिन जाहिर तौर पर ECMAscript ने नहीं चुना है। इस पद्धति में संख्याएं 0000 से लेकर 7FFF सकारात्मक तक होती हैं। नकारात्मक संख्या FFFF (-1) से 8000 तक शुरू होती है।

बेशक, एक ही नियम बड़े पूर्णांकों पर भी लागू होते हैं, लेकिन मैं नहीं चाहता कि मेरा एफ खराब हो। ;)


4
लेकिन क्या आपको यह +0 === -0अजीब नहीं लगता। क्योंकि अब हमारे पास 1 === 1और +0 === -0लेकिन 1/+0 !== 1/-0...
Randomblue

2
बेशक +0 -0 है। यह दोनों कुछ भी नहीं है। लेकिन + इन्फिनिटी और -इनफिनिटी के बीच बहुत बड़ा अंतर है? इनफिनिटी-नंबरों का कारण भी हो सकता है कि ECMA +0 और -1 दोनों का समर्थन करता है।
गोलेज़ट्रोल

आप यह नहीं समझाते हैं कि +0 === -0दो बिट प्रतिनिधित्व अलग होने के बावजूद क्यों ।
Randomblue

1
+0 है -0, 0, कुछ भी नहीं है, नाडा, नियांटे। यह समझ में आता है कि वे समान हैं। आसमान नीला क्यों है? 4 + 3 भी 1 + 6 के समान है, हालांकि अभ्यावेदन अलग हैं। उनके पास अलग-अलग अभ्यावेदन (और इस प्रकार एक अलग सा मूल्य) है, लेकिन जब तुलना की जाती है तो उन्हें उसी शून्य के रूप में संभाला जाता है, जो वे हैं।
GolezTrol

1
वे समान नहीं हैं । इसके उदाहरण के लिए stackoverflow.com/questions/7223717/differentiating-0-and-0 देखें ।
Randomblue

2

हम उपयोग कर सकते हैं Object.is, +0 और -0, और एक और बात अलग करने के लिए NaN==NaN

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

Object.is(NaN,NaN) //true


0

इस घटना को समझाने के लिए विकिपीडिया का एक अच्छा लेख है: http://en.wikipedia.org/wiki/Signed_zero

संक्षेप में, यह +0 और -0 दोनों IEEE फ़्लोटिंग पॉइंट विनिर्देशों में परिभाषित किया गया है। दोनों एक संकेत के बिना 0 से तकनीकी रूप से अलग हैं, जो एक पूर्णांक है, लेकिन व्यवहार में वे सभी शून्य का मूल्यांकन करते हैं, इसलिए सभी व्यावहारिक उद्देश्यों के लिए भेद को अनदेखा किया जा सकता है।


2
यह पूरी तरह से सही नहीं है - 1 / -0 == 1/0 उदाहरण के लिए जावास्क्रिप्ट में झूठी का मूल्यांकन करता है। वे एक जादुई अहस्ताक्षरित शून्य के लिए "मूल्यांकन" नहीं करते हैं, क्योंकि IEEE 754 में "अहस्ताक्षरित पूर्णांक शून्य" जैसी कोई अवधारणा नहीं है।
ब्रेनस्ल्गस83
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.