2011-05-29 12 views
11

में उत्तरदायित्व Count how many different values a list takes in Mathematica का उत्तर तैयार करते समय मैं DeleteDuplicates और Tally दोनों में अस्थिरता (बेहतर अवधि की कमी के लिए) में आया, जो मुझे समझ में नहीं आया।DeleteDuplicates और Tally

पहले विचार करें:

a = {2.2000000000000005, 2.2, 2.1999999999999999}; 

a // InputForm 
[email protected] // InputForm 
[email protected] // InputForm 
[email protected] // InputForm 
 {2.2000000000000006`, 2.2, 2.1999999999999997`}
 {2.2000000000000006`, 2.2, 2.1999999999999997`}
 {2.1999999999999997`, 2.2, 2.2000000000000006`}
 {{2.2000000000000006`, 3}}

यह व्यवहार है जैसा कि मैंने प्रत्येक मामले में की उम्मीद। Tally मामूली संख्यात्मक मतभेदों की भरपाई करता है और प्रत्येक तत्व को बराबर के रूप में देखता है। Union और DeleteDuplicates सभी तत्वों को अद्वितीय के रूप में देखें। (Tally का यह व्यवहार मेरी जानकारी के लिए दस्तावेज नहीं है, लेकिन मैं इससे पहले कि यह का इस्तेमाल किया है।)

अब, इस जटिलता पर विचार करें:

a = {11/5, 2.2000000000000005, 2.2, 2.1999999999999997}; 

a // InputForm 
[email protected] // InputForm 
[email protected] // InputForm 
[email protected] // InputForm 
 {11/5, 2.2000000000000006, 2.2, 2.1999999999999997}
 {11/5, 2.2000000000000006, 2.2}
 {2.1999999999999997, 2.2, 11/5, 2.2000000000000006}
 {{11/5, 1}, {2.2000000000000006, 1}, {2.2, 2}}

Union का आउटपुट अनुमानित है, लेकिन DeleteDuplicates औरदोनों के परिणामआश्चर्यजनक हैं।

  • क्यों DeleteDuplicates अचानक देखता 2.1999999999999997 डुप्लीकेट के रूप में समाप्त हो?

  • Tally अचानक 2.2000000000000006 और 2.2 को अलग के रूप में क्यों देखते हैं, जब यह पहले नहीं था?


एक संबंधित बिंदु के रूप में, यह देखा जा सकता है कि पैक सरणियों Tally प्रभावित करते हैं:

a = {2.2000000000000005, 2.2, 2.1999999999999999}; 
a // InputForm 
[email protected] // InputForm 
 {2.2000000000000006, 2.2, 2.1999999999999997}
 {{2.2000000000000006`, 3}}
a = Developer`[email protected]; 
a // InputForm 
[email protected] // InputForm 
 {2.2000000000000006, 2.2, 2.1999999999999997}
 {{2.2000000000000006`, 1}, {2.2, 2}}

उत्तर

11

प्रदर्शनित व्यवहार चर्चा के तहत कुछ कार्यों में कुछ संदिग्ध व्यवहार के साथ फ़्लोटिंग पॉइंट अंकगणित से जुड़ी सामान्य समस्याओं का परिणाम प्रतीत होता है।

SameQ है नहीं एक तुल्यता संबंध

स्लेट पर पहली: विचार है कि SameQ एक तुल्यता संबंध नहीं है, क्योंकि यह संक्रामक नहीं है:

In[1]:= $a = {11/5, 2.2000000000000005, 2.2, 2.1999999999999997}; 

In[2]:= SameQ[$a[[2]], $a[[3]]] 
Out[2]= True 

In[3]:= SameQ[$a[[3]], $a[[4]]] 
Out[3]= True 

In[4]:= SameQ[$a[[2]], $a[[4]]] 
Out[4]= False      (* !!! *) 

गेट बाहर तो ठीक है, हम अन्य कार्यों में बदलने से पहले भी अनियमित व्यवहार का सामना कर रहे हैं। ,

In[5]:= {# // InputForm, [email protected][#, 2][[1, -10;;]]} & /@ $a[[2;;4]] // TableForm 
(* showing only the last ten binary digits for each *) 
Out[5]//TableForm= 2.2000000000000006 {0,1,1,0,0,1,1,0,1,1} 
        2.2     {0,1,1,0,0,1,1,0,1,0} 
        2.1999999999999997 {0,1,1,0,0,1,1,0,0,1} 

ध्यान दें कि, सख्ती से बोला:

यह व्यवहार SameQ के लिए दस्तावेज शासन का कहना है कि दो वास्तविक संख्या के रूप में "बराबर" इलाज कर रहे हैं अगर वे "अपने पिछले बाइनरी अंक में मतभेद है" की वजह से है $a[[3]] और $a[[4]] अंतिम दो बाइनरी अंकों में भिन्न है, लेकिन अंतर की परिमाण सबसे कम क्रम का एक बिट है।

DeleteDuplicates नहीं सच उपयोग SameQ

इसके बाद, पर विचार प्रलेखन कहा गया है कि कि DeleteDuplicates[...]DeleteDuplicates[..., SameQ] के बराबर है करता है।

In[6]:= DeleteDuplicates[$a] // InputForm 
Out[6]//InputForm= {11/5, 2.2000000000000006, 2.2} 

In[7]:= DeleteDuplicates[$a, SameQ] // InputForm 
Out[7]//InputForm= {11/5, 2.2000000000000006, 2.2} 

एक ही है, के रूप में दस्तावेज ... लेकिन क्या इस बारे में:

In[8]:= DeleteDuplicates[$a, SameQ[#1, #2]&] // InputForm 
Out[8]//InputForm= {11/5, 2.2000000000000006, 2.1999999999999997} 

ऐसा नहीं है कि DeleteDuplicates दिखाई देता है लेकिन अर्थ में शायद नहीं है कि आप उम्मीद कर सकते - ठीक है, कि पूर्णतया सत्य है तर्क की एक अलग शाखा के माध्यम से चला जाता है जब तुलना समारोह SameQ एक समारोह के विपरीत है जिसका व्यवहार SameQ के समान है।

टैली है ...उलझन

Tally समान दिखाता है, लेकिन समान नहीं, अनियमित व्यवहार:

In[9]:= Tally[$a] // InputForm 
Out[9]//InputForm= {{11/5, 1}, {2.2000000000000006, 1}, {2.2, 2}} 

In[10]:= Tally[$a, SameQ] // InputForm 
Out[10]//InputForm= {{11/5, 1}, {2.2000000000000006, 1}, {2.2, 2}} 

In[11]:= Tally[$a, SameQ[#1, #2]&] // InputForm 
Out[11]//InputForm= {{11/5, 1}, {2.2000000000000006, 1}, {2.2000000000000006, 2}} 

पिछले विशेष रूप से चौंकाने है यही कारण है, एक ही नंबर अलग मायने रखता है के साथ सूची में दो बार प्रकट होता है के बाद से।

समान, पीड़ित इसी तरह की समस्याओं

अब वापस चल बिन्दु समानता की समस्या के लिए। EqualSameQ से थोड़ा बेहतर किराया - लेकिन "थोड़ा" पर जोर देता है। Equal अंतिम के बजाय पिछले सात बाइनरी अंक देखता है। यही कारण है कि समस्या हल नहीं होती है, हालांकि ... परेशानी मामलों हमेशा पाया जा सकता है:

In[12]:= $x1 = 0.19999999999999823; 
     $x2 = 0.2; 
     $x3 = 0.2000000000000018; 

In[15]:= Equal[$x1, $x2] 
Out[15]= True 

In[16]:= Equal[$x2, $x3] 
Out[16]= True 

In[17]:= Equal[$x1, $x3] 
Out[17]= False    (* Oops *) 

खलनायक बेपर्दा

इस चर्चा के सभी में मुख्य अपराधी फ्लोटिंग प्वाइंट वास्तविक संख्या है प्रारूप। सीमित प्रारूप का उपयोग करके पूरी तरह से सौम्यता में मनमाना वास्तविक संख्याओं का प्रतिनिधित्व करना संभव नहीं है। यही कारण है कि गणित प्रतीकात्मक रूप पर जोर देता है और जितना संभव हो सके प्रतीकात्मक रूप में अभिव्यक्तियों के साथ काम करने के हर संभव प्रयास करता है। यदि कोई संख्यात्मक रूपों को अपरिहार्य मानता है, तो उसे समानता और असमानता से जुड़े सभी कोने मामलों को हल करने के लिए swamp नामक numerical analysis पर जाना चाहिए।

गरीब SameQ, Equal, DeleteDuplicates, Tally और उनके सभी मित्र कभी मौका नहीं खड़े थे।

+0

धन्यवाद। –

+0

+1 - बहुत अच्छी चर्चा, धन्यवाद! व्यावहारिक दृष्टिकोण से, मैं अभी भी शर्त लगाता हूं कि 'समान' 'समान 'की तुलना में कई और मामलों को संतोषजनक बनाएगा। एक बेहतर परिभाषित समस्या कुछ कठोर ग्रिड (डिब्बे के सेट) के आधार पर समकक्ष वर्गों को परिभाषित करना होगा और यदि वे एक ही "बिन" में समाप्त होते हैं तो दो संख्याओं के बराबर मानें। यह विज्ञापन है, लेकिन अच्छी तरह से परिभाषित है, और शायद कई समस्याओं के लिए अनुचित नहीं है। –

+0

@ लियोनीड और डब्ल्यूआरच, 'ऑर्डर [#, # 2] === 0 और' समानक-एंड-आई-रीली-मीन-इट-टाइम-टाइम के लिए सबसे अच्छा विकल्प है? –

9

मेरी राय में, Tally या DeleteDuplicates डिफ़ॉल्ट (SameQ की तरह आधार पर) की तुलना समारोह और संख्यात्मक मानों क्रियान्वयन संबंधी विवरण पर निर्भर है, क्योंकि SameQ संख्यात्मक मानों पर एक अच्छी तरह से परिभाषित अर्थ विज्ञान नहीं है के साथ के लिए कुछ भी पर भरोसा। जो आप देखते हैं वह सामान्य रूप से अन्य भाषाओं में "अपरिभाषित व्यवहार" कहलाता है।क्या एक मजबूत परिणाम प्राप्त करने के लिए करना चाहिए Union

DeleteDuplicates[a,Equal] 

या

Tally[a,Equal] 

और इसी तरह उपयोग करने के लिए (हालांकि मैं Union का उपयोग नहीं के बाद से स्पष्ट परीक्षण इसके लिए द्विघात जटिलता की ओर जाता है) है। ओटीओएच, यदि आपकी इच्छा आंतरिक कार्यान्वयन के विवरण को समझना है क्योंकि आप उनका उपयोग करना चाहते हैं, तो मैं चेतावनी देने के अलावा बहुत कुछ नहीं कह सकता कि इससे अच्छा से अधिक नुकसान हो सकता है, खासकर क्योंकि इन कार्यान्वयन संस्करण से संस्करण में बदल सकते हैं - यह भी मानते हुए कि आप अपने सभी विवरण कुछ विशेष संस्करण के लिए सही प्राप्त करते हैं।

+0

ऑफ-टॉपिक: इस साइट पर कोई भी सोफार एमएमए के बारे में कुछ नया सीखने के बिना नहीं रहा है। –

+0

मुझे लगता है कि "अपरिभाषित व्यवहार" उचित है, लेकिन किसी भी तरह से मुझे अधिक स्थिरता की उम्मीद है। मुझे लगता है कि हालांकि "अपरिभाषित" का अर्थ है। मुझे लगता है कि यह सिर्फ भाग्य है कि मैं डिफ़ॉल्ट रूप से 'टैली' का उपयोग करने के साथ दूर हो गया हूं। –

+0

'हटाएं डुप्लिकेट [ए, समान]' डिफ़ॉल्ट रूप से डिफ़ॉल्ट रूप से प्रतीत होता है और 'DeleteDuplicates [ए, समान [##] &] ' – Rojo

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^