python - पायथन: नैन की उपस्थिति में सॉर्ट फ़ंक्शन ब्रेक




math sorting (4)

sorted([2, float('nan'), 1]) रिटर्न [2, nan, 1]

(कम से कम सक्रिय पाइथन 3.1 कार्यान्वयन पर।)

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

मैंने max के बारे में एक संबंधित प्रश्न पूछा, और उस पर आधारित मैं समझता हूं कि इस sort क्यों काम करता है। लेकिन क्या इसे एक बग माना जाना चाहिए?

प्रलेखन बस कहता है "किसी भी विवरण को निर्दिष्ट किए बिना" एक नई क्रमबद्ध सूची [...] "लौटें।

संपादित करें: अब मैं सहमत हूं कि यह आईईईई मानक का उल्लंघन नहीं कर रहा है। हालांकि, मुझे लगता है कि यह किसी भी सामान्य ज्ञान दृष्टिकोण से एक बग है। यहां तक ​​कि माइक्रोसॉफ्ट, जो अक्सर अपनी गलतियों को स्वीकार करने के लिए जाना जाता है, ने इसे एक बग के रूप में पहचाना है, और इसे नवीनतम संस्करण में तय किया है: http://connect.microsoft.com/VisualStudio/feedback/details/363379/bug-in-list-double-sort-in-list-which-contains-double-nan

वैसे भी, मैं @ खचिक के जवाब के बाद समाप्त हुआ:

sorted(list_, key = lambda x : float('-inf') if math.isnan(x) else x)

मुझे संदेह है कि यह डिफ़ॉल्ट रूप से करने वाली भाषा की तुलना में प्रदर्शन हिट में परिणाम देता है, लेकिन कम से कम यह काम करता है (मैंने जो भी बग प्रस्तुत किया है) को छोड़कर।


आईईईई 754 मानक है जो इस उदाहरण में फ्लोटिंग पॉइंट ऑपरेशंस को परिभाषित करता है। यह मानक ऑपरेटरों की तुलना संचालन को परिभाषित करता है, जिनमें से कम से कम एक नाइन एक त्रुटि है। इसलिए, यह एक बग नहीं है। आपको अपनी सरणी पर काम करने से पहले NaNs से निपटने की ज़रूरत है।


पिछले उत्तर उपयोगी हैं, लेकिन शायद समस्या की जड़ के बारे में स्पष्ट नहीं हैं।

किसी भी भाषा में, सॉर्ट इनपुट मान के डोमेन पर तुलनात्मक फ़ंक्शन या किसी अन्य तरीके से परिभाषित एक ऑर्डरिंग लागू होता है। उदाहरण के लिए, उर्फ operator <, से कम operator <, का उपयोग पूरे समय और केवल तभी किया जा सकता है जब इनपुट मानों पर उपयुक्त ऑर्डरिंग को परिभाषित किया गया हो।

लेकिन यह विशेष रूप से फ़्लोटिंग पॉइंट मानों के लिए सच नहीं है और इससे कम: "NaN अनियंत्रित है: यह किसी भी चीज़ से अधिक, उससे कम या उससे कम नहीं है।" ( जीएनयू सी मैनुअल से गद्य साफ़ करें, लेकिन सभी आधुनिक IEEE754 आधारित फ्लोटिंग पॉइंट पर लागू होता है)

तो संभावित समाधान हैं:

  1. NaNs को पहले हटाएं, इनपुट डोमेन को अच्छी तरह से परिभाषित करें <(या अन्य सॉर्टिंग फ़ंक्शन का उपयोग किया जा रहा है)
  2. एक कस्टम तुलना फ़ंक्शन (उर्फ predicate) परिभाषित करें जो NaN के लिए ऑर्डरिंग को परिभाषित करता है, जैसे कि किसी भी संख्या से कम, या किसी भी संख्या से अधिक।

किसी भी भाषा में, या तो दृष्टिकोण का उपयोग किया जा सकता है।

व्यावहारिक रूप से, पायथन पर विचार करते हुए, यदि आप या तो सबसे तेज़ प्रदर्शन के बारे में ज्यादा परवाह नहीं करते हैं या नाइन को हटाने के संदर्भ में संदर्भ में वांछित व्यवहार है, तो मैं NaN को हटाना पसंद करूंगा।

अन्यथा आप पुरानी पायथन संस्करणों में, या इसके माध्यम से और functools.cmp_to_key() माध्यम से "cmp" के माध्यम से उपयुक्त पूर्वानुमान फ़ंक्शन का उपयोग कर सकते हैं। बाद में NaNs को हटाने से पहले, स्वाभाविक रूप से थोड़ा अधिक अजीब है। और इस वास्तविक कार्य को परिभाषित करते समय, खराब प्रदर्शन से बचने के लिए देखभाल की आवश्यकता होगी।


मुझे बग के बारे में निश्चित नहीं है, लेकिन कामकाज निम्न हो सकता है:

sorted(
    (2, 1, float('nan')),
    lambda x,y: x is float('nan') and -1 
                or (y is float('nan') and 1
                or cmp(x,y)))

जिसके परिणामस्वरूप:

('nan', 1, 2)

या सॉर्टिंग या कुछ और करने से पहले nan एस को हटा दें।


समस्या यह है कि यदि कोई अनुक्रम ए 1, ए 2, ए 3, ... के बाद से एक एनएएन होता है, तो कोई सही क्रम नहीं होता है, अगर ए 1 <= a2 <= a3 <= ... <= an। यदि इनमें से कोई भी मान एक नैन है तो सॉर्ट की गई संपत्ति टूट जाती है, क्योंकि सभी के लिए, <= NAN और NAN <= a दोनों झूठे हैं।





nan