System.Double '0' (एक संख्या, int?) की तुलना करने का सही तरीका


87

क्षमा करें, यह एक आसान बेवकूफ प्रश्न हो सकता है, लेकिन मुझे यह सुनिश्चित करने के लिए जानना होगा।

मेरी यह ifअभिव्यक्ति है,

void Foo()
{
    System.Double something = GetSomething();
    if (something == 0) //Comparison of floating point numbers with equality 
                     // operator. Possible loss of precision while rounding value
        {}
}

क्या वह अभिव्यक्ति समान है

void Foo()
{
    System.Double something = GetSomething();
    if (something < 1)
        {}
}

? क्योंकि तब मुझे एक समस्या हो सकती है, ifजैसे कि 0.9 के मान के साथ प्रवेश करना ।


3
// Comparison of floating point numbers with equality // operator. क्या आपको वास्तव में यह निर्दिष्ट करने की आवश्यकता है? :)
जॉर्ज जॉनसन

1
मत्स्यावरोध नहीं। 0 और 1 के बीच बहुत सारे मूल्यों का एक नरक है। क्यों न इसे केवल परीक्षण करें और अपने लिए देखें?
Igby Largeman

12
मैंने वैसा ही लिखा जैसा कि Resharper ने किया, यह दिखाने के लिए कि मेरा फोकस कहां है।
रेडबीक्स

@Charles: इसके अलावा, बहुत सारी संख्याएँ हैं जो 0. से कम हैं
ब्रायन

जवाबों:


114

ठीक है, आपको 0 के मान के कितने पास की आवश्यकता है? यदि आप बहुत सारे फ्लोटिंग पॉइंट ऑपरेशंस से गुजरते हैं, जिसमें "अनंत सटीक" का परिणाम 0 हो सकता है, तो आप परिणाम को "बहुत करीब" से 0 तक समाप्त कर सकते हैं।

आमतौर पर इस स्थिति में आप किसी प्रकार का एप्सिलॉन प्रदान करना चाहते हैं, और जांच लें कि परिणाम उस एप्सिलॉन के भीतर है:

if (Math.Abs(something) < 0.001)

एप्सिलॉन जो आपको उपयोग करना चाहिए, वह एप्लिकेशन-विशिष्ट है - यह इस बात पर निर्भर करता है कि आप क्या कर रहे हैं।

बेशक, यदि परिणाम बिल्कुल शून्य होना चाहिए , तो एक साधारण समानता की जांच ठीक है।


वास्तव में, मुझे यह बिल्कुल शून्य होने की आवश्यकता है, यह कैसे दिखेगा? मैंने डबल.जेरो की तलाश की, लेकिन किस्मत जानती है। एक निरंतर अधिकार है? Btw, धन्यवाद, मुझे अब एप्सिलॉन का हिस्सा मिला :)
रेडबीक्स

24
@ ब्रैडबक्स: बस उपयोग करें == 0। आपको वहां एक शाब्दिक मिला है - वह बहुत ही स्थाई है :)
जॉन स्कीट

35

यदि आपको somethingकिसी अन्य ऑपरेशन के परिणाम से सौंपा गया है something = 0तो आप बेहतर उपयोग करते हैं:

if(Math.Abs(something) < Double.Epsilon)
{
//do something
}

संपादित करें : यह कोड गलत है। एप्सिलॉन सबसे छोटी संख्या है, लेकिन काफी शून्य नहीं है। जब आप किसी संख्या को किसी अन्य संख्या से तुलना करना चाहते हैं, तो आपको यह सोचने की आवश्यकता है कि स्वीकार्य सहिष्णुता क्या है। मान लीजिए कि .00001 से परे कुछ भी आप की परवाह नहीं करते हैं। वह संख्या जो आप उपयोग करेंगे। मूल्य डोमेन पर निर्भर करता है। हालाँकि, यह निश्चित रूप से कभी नहीं डबल है। एप्सिलॉन।


2
यह गोलाई समस्या का समाधान नहीं करता है, उदाहरण के Math.Abs(0.1f - 0.1d) < double.Epsilonलिएfalse
थॉमस लुले

6
डबल। एप्सिलॉन ऐसी मजबूरी के लिए बहुत छोटा है। Double.Epsilon सबसे छोटी पॉजिटिव संख्या है जिसे डबल प्रतिनिधित्व कर सकता है।
एवगेनी नाबोकोव

3
इसका कोई मतलब नहीं है क्योंकि यह व्यावहारिक रूप से 0. -1
Gaspa79 के

1
लक्ष्य == का उपयोग किए बिना 0 की अवधारणा के खिलाफ तुलना करना है। कम से कम यह गणितीय रूप से समझ में आता है। मैं मान रहा हूं कि आपके पास एक डबल है और आप इसकी तुलना शून्य = की अवधारणा से करना चाहते हैं। यदि आपका डबल किसी भी कारण से 0d से अलग है, जिसमें राउंडिंग शामिल है, तो टेस्ट भरता है। यह तुलना किसी भी डबल के लिए मान्य लगती है और केवल तभी वापस आएगी जब यह डबल सबसे छोटी संख्या की तुलना में सबसे कम हो, जिसका प्रतिनिधित्व किया जा सकता है, जो 0 की अवधारणा के परीक्षण के लिए एक अच्छी परिभाषा है, नहीं?
सोनाटिक

3
@MaurGi: तुम गलत हो: double d = Math.Sqrt(10100)*2; double a = Math.Sqrt(40400); if(Math.Abs(a - d) < double.Epsilon) { Console.WriteLine("true"); }
sonatique

26

आपका somethingएक है double, और आपने लाइन में सही पहचान की है

if (something == 0)

हमारे पास doubleबायीं ओर (lhs) और intदाहिने हाथ की ओर (rhs) है।

लेकिन अब ऐसा लगता है कि आपको लगता है कि lhs एक में परिवर्तित हो जाएंगे int , और फिर ==साइन दो पूर्णांक की तुलना करेगा। ऐसा नहीं है। रूपांतरण से double करने के लिए int है स्पष्ट और "स्वचालित रूप से" नहीं हो सकता।

इसके बजाय, विपरीत होता है। Rhs में परिवर्तित किया जाता है double, और फिर ==संकेत दो युगल के बीच एक समानता परीक्षण बन जाता है। यह रूपांतरण अंतर्निहित (स्वचालित) है।

लिखना बेहतर (कुछ के द्वारा) माना जाता है

if (something == 0.0)

या

if (something == 0d)

क्योंकि तब यह तत्काल है कि आप दो डबल्स की तुलना कर रहे हैं। हालाँकि, यह सिर्फ शैली और पठनीयता की बात है क्योंकि कंपाइलर किसी भी मामले में यही काम करेगा।

यह कुछ मामलों में प्रासंगिक भी है, जॉन स्केट के उत्तर में "सहिष्णुता" पेश करने के लिए, लेकिन यह भी सहिष्णुता होगी double। यह हो सकता है के पाठ्यक्रम होना1.0 अगर तुम चाहते थे, लेकिन यह हो नहीं है [कम से कम सख्ती से सकारात्मक] पूर्णांक।


17

यदि आप बस चेतावनी को दबाना चाहते हैं, तो यह करें:

if (something.Equals(0.0))

बेशक, यह केवल एक वैध समाधान है यदि आप जानते हैं कि बहाव एक चिंता का विषय नहीं है। मैं अक्सर यह जांचने के लिए करता हूं कि क्या मैं शून्य से विभाजित होने वाला हूं।


4

मुझे नहीं लगता कि यह समान है, ईमानदारी से। योर के स्वयं के उदाहरण पर विचार करें: कुछ = 0.9, या 0.0004। पहले मामले में यह FALSE होगा, दूसरे मामले में यह TRUE होगा। इस प्रकार से निपटना मैं आमतौर पर सटीक प्रतिशत के लिए परिभाषित करता हूं और उस परिशुद्धता के भीतर तुलना करता हूं। अपनी आवश्यकताओं पर निर्भर करता है। कुछ इस तरह...

if(((int)(something*100)) == 0) {


//do something
}

उम्मीद है की यह मदद करेगा।


2
कुछ बिल्कुल शून्य होना चाहिए।
रेडबीक्स

तो तुम भाग्यशाली आदमी हो, इस मामले में :)
टाइगरन

3

यहाँ समस्या पेश करने वाला उदाहरण है (लिनक्यूपैड में तैयार किया गया - यदि आपके पास इसका उपयोग विधि के Console.Writelineबजाय बस नहीं है Dump):

void Main()
{
    double x = 0.000001 / 0.1;
    double y = 0.001 * 0.01; 

    double res = (x-y);
    res.Dump();
    (res == 0).Dump();
}

दोनों x और y सैद्धांतिक रूप से समान और समान हैं: 0.00001 लेकिन "अनंत परिशुद्धता" की कमी के कारण उन मानों में थोड़ा अंतर है। falseसामान्य रूप से 0 से तुलना करने पर दुर्भाग्य से थोड़ा बहुत वापसी ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.