2012-09-01 22 views
11

मुझे पता है कि Double एक रैपर वर्ग है, और यह double नंबर लपेटता है। आज, मैंने एक और मुख्य अंतर देखा है:जावा: तुलना में अलग डबल और डबल

double a = 1.0; 
double b = 1.0; 
Double c = 1.0; 
Double d = 1.0; 
System.out.println(a == b); // true 
System.out.println(c == d); // false 

मेरे साथ अजीब !!!

तो, अगर हम Double, हर बार उपयोग करते हैं, हम कुछ इस तरह करना चाहिए:

private static final double delta = 0.0001; 
System.out.println(Math.abs(c-d) < delta); 

मैं व्याख्या नहीं कर सकते क्यों डबल कर सीधे तुलना गलत। कृपया मेरे लिए समझाओ।

धन्यवाद :)

+8

उपयोग' 'बजाय == की': वस्तुओं प्रकारों के लिए यह हमेशा equals विधि का उपयोग करने के लिए बेहतर है। '==' केवल संदर्भों की जांच करता है। – Baz

+2

@ बाज़ आह, मैं समझता हूं। डबल एक वर्ग है। यह तुलना मूल्य की तुलना में वस्तु की तुलना करेगा। जब हम 'स्ट्रिंग' के साथ करते हैं तो यह समस्या पसंद करती है। '==' :) – hqt

+0

के बजाय 'बराबर' का उपयोग करना चाहिए हां, बिल्कुल ... – Baz

उत्तर

21

c और d तकनीकी रूप से दो अलग-अलग वस्तुओं रहे हैं और == ऑपरेटर केवल संदर्भ तुलना करती है। के रूप में यह मान, नहीं संदर्भ तुलना

c.equals(d) 

बेहतर है। लेकिन अभी भी आदर्श नहीं है। फ्लोटिंग प्वाइंट मूल्यों की तुलना सीधे हमेशा (एप्सिलॉन) खाते (Math.abs(c - d) < epsilon) में कुछ त्रुटि लेना चाहिए।

ध्यान दें कि:

Integer c = 1; 
Integer d = 1; 
यहाँ

तुलना true प्राप्त होते हैं, लेकिन यह अधिक जटिल (Integer आंतरिक कैशिंग, JavaDoc of Integer.valueOf() में वर्णित) है:

इस विधि होगा रेंज में हमेशा कैश मूल्यों - 128 से 127, समावेशी, और इस सीमा के बाहर अन्य मूल्यों को कैश कर सकते हैं।

क्यों valueOf()? क्योंकि इस प्रक्रिया में परोक्ष autoboxing लागू करने के लिए प्रयोग किया जाता है:

Integer c = Integer.valueOf(1); 
Integer d = Integer.valueOf(1); 

भी

+0

ओह। मैंने समझ लिया है। जब हम स्ट्रिंग क्लास के साथ करते हैं तो यह समस्या पसंद करती है। लेकिन आपका दूसरा उदाहरण दिलचस्प है। क्या आप मुझे बता सकते हैं कि पूर्णांक के साथ ऐसा क्यों सच है :) – hqt

+0

@hqt: मेरे उत्तर के * देखें * अनुभाग में लिंक देखें। –

+1

@ एचटीटीटी आप इसे पूर्णांक पूल कह सकते हैं। आकार <-128,127> - इस श्रेणी के भीतर सभी इंटीजर बराबर() 'और' == ' – dantuch

3

जांच के उपयोग equals() 2 वस्तुओं की समानता देखें। == जांचता है कि क्या 2 संदर्भ स्मृति में एक ही ऑब्जेक्ट को संदर्भित करते हैं।

4

जब कक्षा प्रकार के अभिव्यक्तियों पर लागू होता है, ==हमेशा संदर्भ तुलना (JLS section 15.21.3) निष्पादित करेगा। तो इस लाइन:

System.out.println(c == d); 

जाँच कर रहा है कि क्या c और d ही वस्तुओं को देखें। जावा में स्वत: मुक्केबाजी हमेशा (मेरा मानना ​​है कि) float और double के लिए एक नई वस्तु (स्थिति अभिन्न प्रकार के लिए अधिक जटिल है) पैदा करता है। इसलिए c और d विभिन्न ऑब्जेक्ट्स का संदर्भ लें, और इसलिए यह false प्रिंट करता है।

आप समानता के लिए वस्तुओं की तुलना करना चाहते हैं, तो आप equals स्पष्ट रूप से कॉल करने की आवश्यकता:

System.out.println(c.equals(d)); 

double के साथ, यह बजाय संख्यात्मक समानता उपयोग कर रहा है - section 15.21.1 में विनिर्दिष्ट। इसलिए व्यवहार में अंतर।


अभिन्न autoboxing के लिए, "छोटे" मूल्यों कैश नहीं किया जाता - तो autoboxing 5 (माना) एक ही संदर्भ हर बार वापस आ जाएगी। "छोटे" की परिभाषा कार्यान्वयन-विशिष्ट है, लेकिन इसकी सीमा -128 से 127 के भीतर गारंटी है। विवरण के लिए section 5.1.7 के नीचे देखें।

+0

+1 महान विवरण! –

+1

पूर्णांक कैश के बारे में, क्या आप मुझे बता सकते हैं कि आप इसे क्यों जान सकते हैं? मुझे यह सामान किसी भी जावा पुस्तक में नहीं देखा गया है जिसे मैंने पढ़ा है। (और मुझे नहीं लगता कि आप सभी जावा स्पेक सीखते हैं: डी) – hqt

+0

@hqt भले ही आप दिल से सभी spec को नहीं जानते हैं, थोड़ी देर बाद आप इसे अधिक जानते हैं। और यह एक अच्छा अभ्यास है कि जब भी आप ऐसा कुछ देखते हैं जिसे आप नहीं जानते कि यह कैसे काम करता है तो आप चश्मे और/या स्रोत को चेक करते हैं। नया ज्ञान आपको एक बेहतर डेवलपर बनाता है और बग के लिए जोखिम को कम करता है। –

2

सामग्री जांच केवल प्राचीन प्रकार की जांच करते समय == के लिए विश्वसनीय है। `C.equals (घ)

c.equals(d) 
संबंधित मुद्दे