`वेक्टर <फ्लोट> होना चाहिए। ईक्वालस को रिफ्लेक्टिव होना चाहिए या क्या उसे IEEE 754 शब्दार्थ का पालन करना चाहिए?


9

समानता के लिए फ्लोटिंग पॉइंट वैल्यू की तुलना करते समय, दो अलग-अलग दृष्टिकोण होते हैं:

  • NaNखुद के बराबर नहीं है, जो IEEE 754 विनिर्देश से मेल खाता है ।
  • NaNखुद के बराबर होने के नाते, जो रिफ्लेक्सिटी की गणितीय संपत्ति प्रदान करता है जो एक समानता संबंध की परिभाषा के लिए आवश्यक है

सी # (में बिंदु प्रकार चल आईईईई में बनाया गया floatऔर double) के लिए आईईईई अर्थ विज्ञान का पालन करें ==और !=(और संबंधपरक ऑपरेटर की तरह <), लेकिन के लिए रिफ्लेक्सिविटी सुनिश्चित object.Equals, IEquatable<T>.Equals(और CompareTo)।

अब एक पुस्तकालय पर विचार करें जो float/ के ऊपर वेक्टर संरचना प्रदान करता है double। इस तरह का एक वेक्टर प्रकार अधिभार ==/ !=और ओवरराइड object.Equals/ होगा IEquatable<T>.Equals

क्या हर कोई पर सहमत होती है ==/ !=आईईईई अर्थ विज्ञान का पालन करना चाहिए। सवाल यह है कि क्या इस तरह की लाइब्रेरी Equalsपद्धति को लागू करना चाहिए (जो समानता ऑपरेटरों से अलग हो) एक तरह से रिफ्लेक्टिव है या एक तरह से IEEE शब्दार्थ से मेल खाती है।

आईईईई शब्दार्थ का उपयोग करने के लिए तर्क Equals:

  • यह IEEE 754 को फॉलो करता है
  • यह (संभवतः अधिक) तेज़ी से है क्योंकि यह SIMD निर्देशों का लाभ उठा सकता है

    मैंने इस बारे में स्टैकओवरफ्लो पर एक अलग सवाल पूछा है कि आप SIMD निर्देशों और उनके प्रदर्शन प्रभाव का उपयोग करते हुए कैसे प्रतिवर्ती समानता व्यक्त करेंगे: अस्थायी बिंदु समानता तुलना के लिए SIMD निर्देश

    अद्यतन: ऐसा लगता है कि तीन SIMD निर्देशों का उपयोग करके कुशलतापूर्वक रिफ्लेक्सिव समानता को लागू करना संभव है।

  • Equalsफ़्लोटिंग पॉइंट को शामिल करते समय दस्तावेज़ के लिए संवेदनशीलता की आवश्यकता नहीं होती है:

    समान (ऑब्जेक्ट) विधि के सभी कार्यान्वयन के लिए निम्न कथन सही होना चाहिए। सूची में x, yऔर zऑब्जेक्ट संदर्भों का प्रतिनिधित्व करते हैं जो शून्य नहीं हैं।

    x.Equals(x)रिटर्न true, ऐसे मामलों को छोड़कर, जिनमें फ्लोटिंग-पॉइंट प्रकार शामिल हैं। आईएसओ / आईईसी / आईईईई 60559 देखें: 2011, सूचना प्रौद्योगिकी - माइक्रोप्रोसेसर सिस्टम - फ्लोटिंग-पॉइंट अंकगणित।

  • यदि आप फ़्लोट्स का उपयोग कर रहे हैं, तो शब्दकोष कुंजियों के रूप में आप पाप की स्थिति में रह रहे हैं और समझदार व्यवहार की अपेक्षा नहीं करनी चाहिए।

प्रतिवर्त होने के तर्क:

  • यह सहित मौजूदा प्रकार, के साथ संगत है Single, Double, Tupleऔर System.Numerics.Complex

    मैं बीसीएल में किसी भी मिसाल को नहीं जानता जहां Equalsप्रतिवर्त होने के बजाय IEEE का अनुसरण करता है। काउंटर उदाहरणों में शामिल हैं Single, Double, Tupleऔर System.Numerics.Complex

  • Equalsज्यादातर कंटेनरों और खोज एल्गोरिदम द्वारा उपयोग किया जाता है जो रिफ्लेक्सिटी पर भरोसा करते हैं। इन एल्गोरिदम के लिए एक प्रदर्शन लाभ अप्रासंगिक है अगर उन्हें काम करने से रोकता है। प्रदर्शन के लिए शुद्धता का त्याग न करें।
  • यह सब हैश आधारित सेट और शब्दकोशों टूट जाता है, Contains, Find, IndexOfविभिन्न संग्रहों / LINQ, सेट आधारित LINQ परिचालन (पर Union, Exceptआदि) यदि डेटा होता है NaNमानों।
  • कोड जो वास्तविक गणना करता है जहां IEEE शब्दार्थ स्वीकार्य है आमतौर पर ठोस प्रकारों और ==/ !=(या अधिक संभावना एप्सिलॉन तुलना) पर काम करता है ।

    आप वर्तमान में जेनेरिक का उपयोग करके उच्च प्रदर्शन संगणना नहीं लिख सकते क्योंकि आपको इसके लिए अंकगणितीय संचालन की आवश्यकता है, लेकिन ये इंटरफेस या वर्चुअल तरीकों के माध्यम से उपलब्ध नहीं हैं।

    तो एक धीमी Equalsविधि सबसे उच्च प्रदर्शन कोड को प्रभावित नहीं करेगा।

  • यह एक IeeeEqualsविधि या IeeeEqualityComparer<T>उन मामलों के लिए प्रदान करना संभव है जहां आपको या तो IEEE शब्दार्थ की आवश्यकता होती है या आपको प्रदर्शन लाभ की आवश्यकता होती है।

मेरी राय में ये तर्क एक जोरदार कार्यान्वयन के पक्ष में हैं।

Microsoft की CoreFX टीम ने .NET में ऐसे वेक्टर प्रकार की शुरुआत करने की योजना बनाई है। मेरे विपरीत वे IEEE समाधान पसंद करते हैं , मुख्य रूप से प्रदर्शन लाभ के कारण। चूंकि इस तरह का निर्णय निश्चित रूप से एक अंतिम रिलीज के बाद नहीं बदला जाएगा, इसलिए मैं समुदाय से प्रतिक्रिया प्राप्त करना चाहता हूं, जिस पर मैं एक बड़ी गलती मानता हूं।


1
उत्कृष्ट और विचार उत्तेजक प्रश्न। मेरे लिए (कम से कम), इसका कोई मतलब नहीं है ==और Equalsविभिन्न परिणाम लौटाएगा। कई प्रोग्रामर मान वे कर रहे हैं, और कर एक ही बात । इसके अलावा - सामान्य तौर पर, समानता-ऑपरेटरों के कार्यान्वयन Equalsपद्धति को लागू करते हैं । आपने तर्क दिया है कि एक में एक शामिल हो सकता है IeeeEquals, लेकिन एक इसे दूसरे तरीके से भी कर सकता है और इसमें एक ReflexiveEqualsएमथोड शामिल है । Vector<float>प्रकार में इस्तेमाल किया जा सकता कई प्रदर्शन महत्वपूर्ण अनुप्रयोगों, और उसके अनुसार अनुकूलित किया जाना चाहिए।
मर मौस

@diemaus कुछ कारणों से मुझे यह समझाने में असमर्थता है: 1) float/ doubleऔर कई अन्य प्रकारों के लिए, ==और Equalsपहले से ही अलग हैं। मुझे लगता है कि मौजूदा प्रकारों के साथ एक विसंगति भी असंगतता के बीच की तुलना में अधिक भ्रामक होगी ==और Equalsआपको अभी भी अन्य प्रकारों से निपटना होगा। 2) बहुत सारे जेनेरिक एल्गोरिदम / संग्रह उपयोग Equalsकरते हैं और फ़ंक्शन (LINQ और शब्दकोशों) के लिए इसकी संवेदनशीलता पर भरोसा करते हैं, जबकि कंक्रीट फ्लोटिंग-पॉइंट एल्गोरिदम आमतौर पर ==उनका IEEE शब्दार्थ प्राप्त करते हैं।
कोडइन्चोस

मैं Vector<float>एक साधारण floatया से अलग "जानवर" पर विचार करूंगा double। उस उपाय से, मैं Equalsया ==ऑपरेटर को उनके मानकों का पालन करने का कारण नहीं देख सकता। आपने खुद कहा: "यदि आप फ़्लोट्स का उपयोग कर रहे हैं तो शब्दकोश कुंजियों के रूप में आप पाप की स्थिति में रह रहे हैं और उन्हें समझदार व्यवहार की उम्मीद नहीं करनी चाहिए"। यदि कोई NaNएक शब्दकोश में संग्रहित करता है, तो यह भयानक अभ्यास का उपयोग करने के लिए अपने स्वयं के ईश्वरीय दोष है। मुझे शायद ही लगता है कि CoreFX-team ने ऐसा नहीं सोचा था। मैं ReflexiveEqualsप्रदर्शन के लिए सिर्फ एक या समान के साथ जाऊँगा ।
डाई मौस

जवाबों:


5

मैं तर्क दूंगा कि IEEE व्यवहार सही है। NaNs किसी भी तरह से एक दूसरे के बराबर नहीं हैं; वे अ-परिभाषित परिस्थितियों के अनुरूप हैं जहाँ एक संख्यात्मक उत्तर उचित नहीं है।

IEEE अंकगणित के उपयोग से आने वाले प्रदर्शन लाभों से परे जो कि अधिकांश प्रोसेसर मूल रूप से समर्थन करते हैं, मुझे लगता है कि यह कहने के साथ एक अर्थ समस्या है कि अगर isnan(x) && isnan(y), तब x == y। उदाहरण के लिए:

// C++
double inf = std::numeric_limits<double>::infinity();
double x = 0.0 / 0.0;
double y = inf - inf;

मैं यह तर्क दूंगा कि कोई भी सार्थक कारण नहीं है कि कोई इसके xबराबर क्यों सोचे y। आप शायद ही निष्कर्ष निकाल सकते हैं कि वे समान संख्या में हैं; वे बिल्कुल भी संख्या नहीं हैं, इसलिए यह पूरी तरह से एक अमान्य अवधारणा की तरह लगता है।

इसके अलावा, एक एपीआई डिजाइन के नजरिए से, यदि आप एक सामान्य-उद्देश्य पुस्तकालय पर काम कर रहे हैं जिसका उद्देश्य कई प्रोग्रामर द्वारा उपयोग किया जाना है, तो यह सबसे अधिक उद्योग-विशिष्ट फ्लोटिंग-पॉइंट शब्दार्थ का उपयोग करने के लिए समझ में आता है। एक अच्छे पुस्तकालय का लक्ष्य उन लोगों के लिए समय की बचत करना है जो इसका उपयोग करते हैं, इसलिए गैर-व्यवहारात्मक व्यवहार में निर्माण भ्रम की स्थिति है।


3
यह NaN == NaNगलत होना चाहिए निर्विवाद है। सवाल यह है कि .Equalsविधि क्या करना चाहिए। उदाहरण के लिए यदि मैं NaNएक शब्दकोश कुंजी के रूप में उपयोग करता हूं , तो संबंधित मूल्य NaN.Equals(NaN)गलत हो जाता है यदि वह गलत है।
कोडइन्चोस

1
मुझे लगता है कि आपको सामान्य मामले के लिए अनुकूलित करना होगा। संख्या के वेक्टर के लिए सामान्य मामला उच्च थ्रूपुट संख्यात्मक गणना (अक्सर SIMD निर्देशों के साथ अनुकूलित) है। मैं तर्क दूंगा कि एक सदिश शब्दकोष के रूप में एक वेक्टर का उपयोग करना एक अत्यंत दुर्लभ उपयोग मामला है, और एक शायद ही आपके शब्दार्थ को डिजाइन करने के लायक है। प्रतिरोध्य दलीलें जो मेरे लिए सबसे उचित लगता है, सामंजस्य है, क्योंकि मौजूदा Single, Doubleआदि वर्गों को पहले से ही कर्मकर्त्ता व्यवहार किया है। IMHO, यह सिर्फ गलत निर्णय के साथ शुरू करने के लिए था। लेकिन मैं लालित्य को उपयोगिता / गति के रास्ते में नहीं आने दूंगा।
जेसन आर

लेकिन संख्यात्मक अभिकलन आमतौर पर ==IEEE का अनुसरण करते हैं, इसलिए वे तेजी से कोड Equalsको लागू करने से कोई फर्क नहीं पड़ता । IMO एक अलग Equalsविधि होने के पूरे बिंदु को एल्गोरिदम में उपयोग कर रहा है जो कि LINQ के Distinct()फ़ंक्शन जैसे ठोस प्रकार की परवाह नहीं करता है।
कोडइन्चोस

1
मै समझ गया। लेकिन मैं एक एपीआई के खिलाफ तर्क दूंगा जिसमें एक ==ऑपरेटर और एक Equals()फ़ंक्शन है जिसमें विभिन्न शब्दार्थ हैं। मुझे लगता है कि आप डेवलपर दृष्टिकोण से संभावित भ्रम की लागत का भुगतान कर रहे हैं, जिसका कोई वास्तविक लाभ नहीं है (मैं शब्दकोश कुंजी के रूप में संख्याओं के वेक्टर का उपयोग करने में सक्षम होने के लिए कोई मूल्य प्रदान नहीं करता हूं)। यह सिर्फ मेरी राय है; मुझे नहीं लगता कि सवाल का कोई वस्तुनिष्ठ उत्तर हाथ में है।
जेसन आर

0

एक समस्या है: IEEE754 रिलेशनल ऑपरेशंस और समानता को एक तरह से परिभाषित करता है जो संख्यात्मक अनुप्रयोगों के लिए अच्छी तरह से अनुकूल है। यह छँटाई और हैशिंग के लिए अच्छी तरह से अनुकूल नहीं है। इसलिए यदि आप संख्यात्मक मानों के आधार पर एक सरणी को क्रमबद्ध करना चाहते हैं, या यदि आप संख्यात्मक मानों को एक सेट में जोड़ना चाहते हैं या उन्हें किसी शब्दकोश में कुंजियों के रूप में उपयोग करना चाहते हैं, तो आप या तो घोषणा करते हैं कि NaN मानों की अनुमति नहीं है, या आप IEEE754 का उपयोग नहीं करते हैं अंतर्निहित कार्य। आपकी हैश तालिका को यह सुनिश्चित करना होगा कि सभी NaN एक ही मूल्य से मेल खाते हैं, और एक दूसरे के बराबर तुलना करें।

यदि आप वेक्टर को परिभाषित करते हैं तो आपको डिज़ाइन निर्णय करना होगा कि क्या आप इसे केवल संख्यात्मक उद्देश्यों के लिए उपयोग करना चाहते हैं या क्या यह छँटाई और हैशिंग के साथ संगत होना चाहिए। मैं व्यक्तिगत रूप से सोचता हूं कि संख्यात्मक उद्देश्य अधिक महत्वपूर्ण होना चाहिए। यदि छँटाई / हैशिंग की आवश्यकता है तो आप वेक्टर के साथ एक वर्ग को एक सदस्य के रूप में लिख सकते हैं और उस वर्ग में हैशिंग और समानता को परिभाषित कर सकते हैं जिस तरह से आप चाहते हैं।


1
मैं मानता हूं कि संख्यात्मक उद्देश्य अधिक महत्वपूर्ण हैं। लेकिन हमारे पास पहले से ही उनके लिए ==और !=ऑपरेटर हैं। मेरे अनुभव में यह Equalsविधि बहुत ही गैर-संख्यात्मक एल्गोरिदम द्वारा उपयोग की जाती है।
कोडइन्चोस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.