2009-08-28 11 views
19

मान लीजिए कि हमारे पास एन संख्याएं हैं (पूर्णांक, फ्लोट्स, जो कुछ भी आप चाहते हैं) और अपने अंकगणितीय माध्य को ढूंढना चाहते हैं। सरलतम विधि मूल्यों की संख्या से सभी मूल्यों और भाग कर योग करने के लिए है:क्या अंक()/एन से अंकगणितीय माध्य "बेहतर" खोजने का कोई तरीका है?

def simple_mean(array[N]): # pseudocode 
    sum = 0 
    for i = 1 to N 
     sum += array[i] 
    return sum/N 

यह ठीक काम करता है, लेकिन बड़ी पूर्णांकों की आवश्यकता है। यदि हम बड़े पूर्णांक नहीं चाहते हैं और हम गोल करने वाली त्रुटियों के साथ ठीक हैं, और एन दो की शक्ति है, तो हम 'divide-and-conquer' का उपयोग कर सकते हैं: ((a+b)/2 + (c+d)/2)/2 = (a+b+c+d)/4, ((a+b+c+d)/4 + (e+f+g+h)/4)/2 = (a+b+c+d+e+f+g+h)/8, आदि।

def bisection_average(array[N]): 
    if N == 1: return array[1] 
    return (bisection_average(array[:N/2])+bisection_average(array[N/2:]))/2 

कोई अन्य तरीका?

पीएस। playground for lazy

+0

दिलचस्प है, लेकिन 'राउंडिंग त्रुटियों के साथ ठीक' के बारे में मुझे थोड़ा चिंतित है। मैं कोई त्रुटि के साथ एक विधि पसंद करेंगे। – pavium

+0

दूसरे विचारों पर, मैं सुबह में वापस आऊंगा और मेरा जवाब मिटा दूंगा अगर मैं अभी भी खुश हूं कि यह बहुत गलत नहीं है ... –

+0

@ पैवियम: यदि आप कोई त्रुटि नहीं चाहते हैं, तो आपको गणना करने की आवश्यकता है हाथ से यह – MusiGenesis

उत्तर

3

बड़ा पूर्णांक समस्या हैं ... यह ठीक

a/N + b/N+.... n/N 

मेरा मतलब है तुम सिर्फ अन्य तरीकों या इष्टतम तरीका ढूंढ रहे हैं क्या है?

+2

क्यों?!? यदि ए, बी, आदि पूर्णांक हैं तो यह आपको गलत जवाब देगा। अगर वे फ़्लोटिंग प्वाइंट हैं, तो मुझे यकीन नहीं है, लेकिन मेरा झुकाव है कि अगर आप अभी एक योग करते हैं और फिर विभाजित होते हैं तो आपको अधिक गोल करने वाली त्रुटियां मिलेंगी। किसी भी मामले में एक संदिग्ध लाभ के लिए गणना समय काफी बढ़ गया है। –

1

यदि आप float का उपयोग आप बड़े पूर्णांकों से बचने के सकता है:

def simple_mean(array[N]): 
    sum = 0.0 # <--- 
    for i = 1 to N 
     sum += array[i] 
    return sum/N 
28

नुथ फ्लोटिंग बिंदु (मूल पी पर Vol 2 of The Art of Computer Programming के 232, 1998 संस्करण दिए गए माध्य और मानक विचलन की गणना के लिए सूचीबद्ध करता है निम्न विधि; नीचे मेरी अनुकूलन। से बचा जाता है विशेष आवरण पहले यात्रा):

double M=0, S=0; 

for (int i = 0; i < N; ++i) 
{ 
    double Mprev = M; 
    M += (x[i] - M)/(i+1); 
    S += (x[i] - M)*(x[i] - Mprev); 
} 

// mean = M 
// std dev = sqrt(S/N) or sqrt(S/N+1) 
// depending on whether you want population or sample std dev 
+0

'एस + = (एक्स [i] - एम) * (x [i] - Mprev) नहीं होना चाहिए;' '+ + (x [i] - Mprev) * (x [i] - Mprev);' ? –

+1

नं। Http://jonisalonen.com/2013/deriving-welfords-method-for-computing-variance/ –

17

यहाँ त्रुटियों गोलाई और बड़े मध्यवर्ती मूल्यों से परहेज बिना सिर्फ पूर्णांकों का उपयोग कर मतलब गणना करने के लिए एक तरीका है:

sum = 0 
rest = 0 
for num in numbers: 
    sum += num/N 
    rest += num % N 
    sum += rest/N 
    rest = rest % N 

return sum, rest 
+0

+1 बहुत चालाक देखें! –

+0

यह मूल रूप से बहुप्रवाह (दोहरी शब्द) अंकगणित का उपयोग करता है। मुझे लगता है कि विभाजन की तरह (/ या%) संचालन की संख्या प्राप्त करने के लिए इसे अनुकूलित करने का एक तरीका है, लेकिन मुझे अपने सिर के ऊपर से याद नहीं है। –

+0

सामान्य तकनीक एक एकल समारोह/एकल ऑपरेशन में एक्स/एन और एक्स% एन की गणना करना है। ऐसा इसलिए है क्योंकि अंतर्निहित एल्गोरिदम काफी समान हैं। – MSalters

3

यदि सरणी फ़्लोटिंग-पॉइंट डेटा है, तो "सरल" एल्गोरिदम भी गोल त्रुटि से पीड़ित है। दिलचस्प बात यह है कि, उस मामले में, वर्ग वर्ग (एन) की वर्ग वर्ग (एन) की गणना में गणना को अवरुद्ध करना वास्तव में औसत मामले में त्रुटि को कम करता है (भले ही फ़्लोटिंग-पॉइंट राउंडिंग की संख्या समान हो)।

पूर्णांक डेटा के लिए, ध्यान दें कि आपको सामान्य "बड़े पूर्णांक" की आवश्यकता नहीं है; यदि आपके सरणी (संभवतः) में 4 बिलियन से कम तत्व हैं, तो आपको सरणी डेटा के प्रकार की तुलना में केवल एक पूर्णांक प्रकार 32 बिट्स की आवश्यकता होती है। इस थोड़ा बड़े प्रकार पर अतिरिक्त प्रदर्शन करना हमेशा प्रकार पर विभाजन या मॉड्यूलस करने से काफी तेज होगा। उदाहरण के लिए, अधिकांश 32 बिट सिस्टम पर, 64-बिट अतिरिक्त 32-बिट विभाजन/मॉड्यूलस से तेज़ है। यह प्रभाव केवल अधिक अतिरंजित हो जाएगा क्योंकि प्रकार बड़े हो जाते हैं। O(n) - -

0

Kahan algorithm (विकिपीडिया के अनुसार) बेहतर क्रम प्रदर्शन (जोड़ो में योग की तुलना में) है और एक O(1) त्रुटि विकास:

function KahanSum(input) 
    var sum = 0.0 
    var c = 0.0     // A running compensation for lost low-order bits. 
    for i = 1 to input.length do 
     var y = input[i] - c  // So far, so good: c is zero. 
     var t = sum + y   // Alas, sum is big, y small, so low-order digits of y are lost. 
     c = (t - sum) - y // (t - sum) recovers the high-order part of y; subtracting y recovers -(low part of y) 
     sum = t   // Algebraically, c should always be zero. Beware overly-aggressive optimizing compilers! 
     // Next time around, the lost low part will be added to y in a fresh attempt. 
    return sum 

इसका विचार यह है कि चल बिन्दु संख्या के कम बिट्स मुख्य सारांश से स्वतंत्र रूप से संक्षेप में और सही किया जाता है।

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