+0 और -0 इंट और फ्लोट डेटा के लिए अलग-अलग व्यवहार दिखाता है


16

मैंने इस पोस्ट को नकारात्मक और सकारात्मक शून्य पढ़ा है

मेरी समझ निम्नलिखित कोड देना चाहिए करने के लिए true और true एक आउटपुट के रूप में।

हालांकि, यह दे रहा है falseऔर trueएक आउटपुट के रूप में।

मैं नकारात्मक शून्य की तुलना सकारात्मक शून्य से कर रहा हूं।

public class Test {
     public static void main(String[] args) {
            float f = 0;
            float f2 = -f;
            Float F = new Float(f);
            Float F1 = new Float(f2);
            System.out.println(F1.equals(F));

            int i = 0;
            int i2 = -i;
            Integer I = new Integer(i);
            Integer I1 = new Integer(i2);
            System.out.println(I1.equals(I));
      }
  }

हम 0 के लिए अलग व्यवहार क्यों करते हैं Integerऔर Float?


11
यदि आप javadocs, docs.oracle.com/javase/8/docs/api/java/lang/… चेक करते हैं, तो परिभाषा हैश टेबल को ठीक से काम करने की अनुमति देती है। इसके अलावा, कोई -0 पूर्णांक नहीं है।
मैट

@ मट अगर -0 पूर्णांक नहीं है तो इसका मूल्यांकन असत्य के रूप में किया जाना चाहिए ...
जोकर

3
जब आप i2 = -i कहते हैं; i2, i का सटीक सा प्रतिनिधित्व करता है, उन्हें समझने का कोई तरीका नहीं है। iऔर i2बिल्कुल समान हैं। फिर जब आप नई Integerएस बनाते हैं तो वे दोनों एक ही मूल्य को लपेटते हैं। I1.equals(I)सच होगा।
मैट

1
कोशिश करें int i = Integer.MIN_VALUE, i2 = -i;...
Holger

1
वैसे, newयहां रैपर प्रकारों का उपयोग करने का कोई कारण नहीं है। बस का उपयोग करें, जैसेInteger i = 0, i2 = -i; System.out.println(i.equals(i2)); Float f1 = 0f, f2 = -f1; System.out.println(f1.equals(f2));
Holger

जवाबों:


19

जावा में इन्ट्स और फ्लोट्स बहुत अलग जानवर हैं। इनट्स को दो के पूरक के रूप में एन्कोड किया गया है , जिसमें एक 0 मान है। फ़्लोट्स IEEE 754 ( फ़्लोट्स के लिए 32-बिट वेरिएंट , और डबल्स के लिए 64-बिट ) का उपयोग करते हैं। IEEE 754 कुछ जटिल है, लेकिन इस उत्तर के उद्देश्य के लिए, आपको बस यह जानना होगा कि इसके तीन खंड हैं, जिनमें से पहला एक संकेत बिट है। इसका मतलब है कि किसी भी फ्लोट के लिए, एक सकारात्मक और नकारात्मक संस्करण है। इसमें 0 शामिल हैं, इसलिए फ्लोट्स में वास्तव में दो "शून्य" मान हैं, +0 और -0।

एक तरफ के रूप में, दो का पूरक जो कि इनट्स का उपयोग करता है, कंप्यूटर विज्ञान में पूर्णांकों को एनकोड करने का एकमात्र तरीका नहीं है। अन्य विधियां हैं, जैसे लोगों के पूरक , लेकिन उनके पास quirks हैं - जैसे कि +0 और -0 दोनों अलग-अलग मानों के रूप में। ;-)

जब आप फ्लोट प्रिमिटिव (और डबल्स) की तुलना करते हैं, तो जावा +0 और -0 को समान मानता है। लेकिन जब आप उन्हें बॉक्स करते हैं, तो जावा उन्हें अलग से व्यवहार करता है, जैसा कि इसमें वर्णित है Float#equals। इससे बराबरी का तरीका उनके hashCodeकार्यान्वयन (साथ ही compareTo) के अनुरूप हो जाता है , जो सिर्फ फ्लोट के बिट्स (उस पर हस्ताक्षरित मूल्य सहित) का उपयोग करता है और उन्हें एक अंतर में बदल देता है।

वे बराबरी / हैशकोड / तुलना के लिए कुछ अन्य विकल्प चुन सकते थे, लेकिन उन्होंने ऐसा नहीं किया। मुझे यकीन नहीं है कि वहाँ डिजाइन विचार क्या थे। लेकिन कम से कम एक संबंध में, Float#equalsहमेशा फ्लोट आदिम से विचलन करने जा रहा था ==: आदिम में NaN != NaN, लेकिन सभी वस्तुओं के लिए, o.equals(o)यह भी सच होना चाहिए । इसका मतलब है कि अगर आपके पास था Float f = Float.NaN, तो f.equals(f)भी f.floatValue() != f.floatValue()


¹ NaN (नहीं-एक-संख्या) मानों में एक साइन बिट है, लेकिन इसका ऑर्डर करने के अलावा कोई अर्थ नहीं है, और जावा इसे (यहां तक ​​कि ऑर्डर करने के लिए) भी अनदेखा करता है।


10

यह फ्लोट के अपवादों में से एक है

दो अपवाद हैं:

यदि f1 + 0.0f का प्रतिनिधित्व करता है , जबकि f2 -0.0f का प्रतिनिधित्व करता है , या इसके विपरीत, बराबर परीक्षण में मान गलत है

क्यों वर्णित है:

यह परिभाषा हैश टेबल को ठीक से संचालित करने की अनुमति देती है।

-0 और 0 फ्लोट की बिट 31 का उपयोग करते हुए अलग तरह से प्रतिनिधित्व करेंगे:

बिट 31 (बिट जो मास्क 0x80000000 द्वारा चुना गया है) फ्लोटिंग-पॉइंट नंबर के संकेत को दर्शाता है।

यह मामला नहीं है Integer


सवाल है क्यों? क्या यह कठिन और तेज़ नियम है कि हमें रटना है :(
जोकर

@ जोकर जोड़ा गया हैश तालिकाओं को ठीक से संचालित करने की अनुमति देता है
user7294900

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

@yshavit धन्यवाद, क्या आप एक जवाब के रूप में एक ही साझा कर सकते हैं
जोकर

3
@ जोकर बिट 31 (मुखौटा 0x80000000 द्वारा चयनित बिट) फ़्लोटिंग-पॉइंट संख्या के संकेत का प्रतिनिधित्व करता है।
user7294900

5

पूर्णांक के लिए, पूर्णांक के लिए -0 और 0 के बीच कोई अंतर नहीं है क्योंकि यह Twos तारीफ प्रतिनिधित्व का उपयोग करता है । तो आपके पूर्णांक उदाहरण iऔर i1बिल्कुल समान हैं।

फ़्लोट्स के लिए, -0 प्रतिनिधित्व है, और यह मान 0 के बराबर है, लेकिन बिट प्रतिनिधित्व अलग है। इसलिए नए फ्लोट (0f) और नए फ्लोट (-0f) का अलग-अलग प्रतिनिधित्व होगा।

आप बिट अभ्यावेदन में अंतर देख सकते हैं।

System.out.println(Float.floatToIntBits(-0f) + ", " + Float.floatToIntBits(0f));

-2147483648, 0

और यदि आप इसे fघोषित करने के लिए छोड़ देते हैं -0fतो इसे पूर्णांक माना जाएगा, और आपको आउटपुट में कोई अंतर नहीं दिखेगा।


और फिर भी आदिम नाव उस के साथ ठीक काम करती है। यही कारण है 0.0f == -0.0f। तो अलग व्यवहार केवल में है java.lang.Float
ivant

3
IEEE754 के अनुसार @ivant, "सामान्य तुलना संचालन, हालांकि, NaNs को असमान मानते हैं और as0 और +0 की तुलना" en.m.wikipedia.org/wiki/IEEE_754
टर्नर

@AndyTurner, हाँ मैं समझता हूँ कि। मैं सिर्फ इशारा कर रहा हूं कि जावा में आदिम प्रकार के बीच व्यवहार में अंतर है float, जो इस संबंध में IEEE754 के अनुरूप है और java.lang.Floatजो नहीं करता है। तो बस बिट प्रतिनिधित्व में अंतर यह समझाने के लिए पर्याप्त नहीं है।
ivant
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.