2011-05-27 10 views
7

के साथ हस्ताक्षरित डिवीजन मैं रोलिंग औसत की गणना करने की कोशिश कर रहा हूं, और थोड़ी कोशिश करने और प्राप्त करने और अनुकूलित करने के लिए, मैंने गणना को सरल बना दिया है, इसलिए केवल एक ही विभाजन है। जब मूल्य कम हो रहा है, तो एक बिंदु है जहां वर्तमान मूल्य औसत से कम हो जाता है। इस बिंदु पर औसत कूदता है। मुझे कल्पना है कि ऐसा इसलिए है क्योंकि विभाजन को हस्ताक्षरित किया गया है, और मेरे न्यूमेरेटर के साइन बिट को बड़े पैमाने पर हस्ताक्षरित संख्या के रूप में व्याख्या किया गया है। मुझे यकीन नहीं है कि इस समस्या को बीमा करने के लिए मुझे हस्ताक्षर किए जाने की आवश्यकता क्यों है, फिर से दिखाई नहीं दे रहा है।हस्ताक्षरित संख्या

unsigned int AverageUsage; 
unsigned int TotalUsage; 
unsigned int incCount; 

    AverageUsage = (TotalUsage - AverageUsage)/++incCount + AverageUsage; 

AverageUsage हमेशा धनात्मक रहेगी, लेकिन जब TotalUsage AverageUsage नीचे चला जाता है, मुझे यकीन है कि क्या विभाजन

AverageUsage = (signed int)(TotalUsage - AverageUsage)/++incCount + AverageUsage; 

अंश सेट हो जाएगा पर हस्ताक्षर किए के साथ की उम्मीद नहीं कर रहा हूँ, लेकिन मुझे यकीन है कि नहीं कर रहा हूँ विभाजन कैसे होगा।

AverageUsage = (signed int)((signed int)(TotalUsage - AverageUsage)/++incCount) + AverageUsage; 

काम करना चाहिए (मैं इस पूर्ण आपरेशन के परिणाम की गारंटी नकारात्मक कभी नहीं होगा सकते हैं), लेकिन मैं मामलों के बारे में चिंतित हूँ जब incCount कि 'दिखता है' नकारात्मक एक मूल्य तक पहुँचता है। एक अगर बयान

  • QWORDs
  • धन्यवाद की आवश्यकता नहीं है

    • जरूरत नहीं है:

      वहाँ कि उम्मीद है कि यह करने के लिए एक सरल उपाय है!

    +3

    यदि आप इन सभी चरों की घोषणा शामिल करते हैं तो इससे मदद मिलेगी। सी के पदोन्नति नियम विभिन्न उप-अभिव्यक्तियों के प्रकारों पर निर्भर करते हैं। उदाहरण के लिए, औसत उपयोग एक int है? हस्ताक्षरित int? हस्ताक्षरित छोटा? आदि – Nemo

    +0

    मुझे इस कोड का संदेह है; क्या आप सुनिश्चित हैं कि यह अंकगणितीय रूप से सही है और "संचयी औसत" की बजाय "रोलिंग औसत" की गणना करता है? रोलिंग औसत को "हाल के मूल्यों" के बफर की आवश्यकता होगी। – Clifford

    +0

    @ क्लाइफोर्ड। यह एक बुनियादी आईआईआर है। आप शायद एक इंटीग्रेटर-कंघी एफआईआर के बारे में सोच रहे हैं; जो सांख्यिकीय नमूना मतलब (चल रहा/रोलिंग) के बराबर है। भले ही, वे दोनों सही हैं; जनसंख्या के लिए कम-पास फ़िल्टर और अनुमान के रूप में। –

    उत्तर

    4

    आपके पास 2 विकल्प हैं।

    उपयोग फ्लोटिंग प्वाइंट मठ

    मुझे लगता है कि आप ऐसा करने के लिए वैसे भी एक उचित औसत प्राप्त करना चाहते हैं।

    मिश्रित फ़्लोटिंग/पूर्णांक विभाजन जैसी कोई चीज़ नहीं है। तो, दोनों संख्यात्मक और denominator दोनों एक फ्लोटिंग बिंदु में परिवर्तित हो जाएगा।

    चाहे संख्यात्मक या denominator हस्ताक्षरित या हस्ताक्षरित है, इससे कोई फर्क नहीं पड़ता। हस्ताक्षर किए गए फ्लोटिंग पॉइंट जैसी कोई चीज नहीं है। Denominator incCount को एक फ़्लोटिंग पॉइंट में परिवर्तित कर दिया जाएगा और पूर्ण फ़्लोटिंग पॉइंट डिवीजन किया जाएगा।

    उपयोग पूर्णांक विभाजन और संभाल विशेष मामलों

    किसी कारण से आप, तो दोनों अंश और हर पूर्णांक विभाजन के साथ रहना चाहते हैं एक ही हस्ताक्षर किए/अहस्ताक्षरित प्रकार रहना होगा।

    दोनों अंश/विभाजक

    incCount प्रवेश किया हुआ है एक हस्ताक्षरित संख्या में परिवर्तित हो जाएगा। यदि यह बहुत बड़ा है तो यह नकारात्मक संख्या की तरह दिखेगा और आपका उत्तर गलत होगा। आपको इस अतिप्रवाह के लिए परीक्षण करना होगा।TotalUsage < AverageUsage और TotalUsage > AverageUsage:

    दोनों अंश/विभाजक अहस्ताक्षरित

    आप अंश अहस्ताक्षरित बनाने के लिए और दो मामलों को संभालने के लिए एक अगर() कथन का उपयोग करने के लिए है रहे हैं। यहां incCount पूर्णांक बिट्स की पूरी श्रृंखला का उपयोग कर सकता है क्योंकि इसे एक हस्ताक्षरित संख्या के रूप में माना जाएगा।

    +0

    ठीक है समझ में आता है। मुझे पूर्णांक विभाजन चाहिए क्योंकि मैं स्मृति उपयोग (बाइट्स में) को ट्रैक कर रहा हूं जो लगभग हमेशा 50 + एमबी रेंज में होगा। बाइट्स के खंड कोई चिंता नहीं है। मैं एक एफपीयू के बिना एआरएम पर भी काम कर रहा हूं। – Gdogg

    1

    ध्यान दें कि यह मानक औसत नहीं है। एक मानक औसत होगा:

    Averageusage = TotalUsage/++incCount 
    

    मान लिया जाये कि (आदर्श) है कि incCount कुछ उपयोगी समय-समय पर बढ़ते मूल्य (सेकंड) की तरह है।

    एक खस्ताहाल औसत आमतौर पर अधिक की तरह कार्यान्वित किया जाता है: http://donlehmanjr.com/Science/03%20Decay%20Ave/032.htm जो अगर मैं सही ढंग से अनुवाद किया है:

    AverageUsage = TotalUsage/(incCount+1) + incCount/(incCount+1) * AverageUsage; 
    incCount++; 
    

    हिमाद्री उल्लेख किया है, शायद ये चल बिन्दु गणित में किया जाना चाहिए। int, unsigned int, long, unsigned long, intmax_t, uintmax_t, float, double, long double:

    +0

    मैं आवश्यक डिवीजनों की संख्या को कम करने की कोशिश कर रहा था। मेरा सूत्र आपके लिए एक सरलीकरण है। – Gdogg

    +0

    @Gdogg: जब तक आपके पास कुछ प्रयोगात्मक सबूत नहीं हैं, यह सुझाव देते हुए कि यह एक हॉटस्पॉट है, मैं दृढ़ता से सुझाव देता हूं कि आप समयपूर्व अनुकूलन कर रहे हैं। एक सही, मानक, एल्गोरिदम का उपयोग करने से आपके उपयोगकर्ताओं को खुश कर दिया जा रहा है क्योंकि यह सही ढंग से दर्शाता है कि जब लोग औसत देखते हैं तो लोग क्या अपेक्षा करते हैं। –

    +0

    सरलीकरण सिर्फ प्रदर्शन के बारे में नहीं है। इसकी अभिव्यक्ति अभ्यास में बुरी तरह टूट जाती है; '(incCount/(incCount + 1)) 'हमेशा पूर्णांक अंकगणित में शून्य है। यदि आप '(incCount * औसत उपयोग)/(incCount + 1) 'में पुनर्व्यवस्थित करते हैं, तो आप संख्या में ओवरफ़्लो जोखिम लेते हैं। –

    5

    सी बाइनरी ऑप्स (विभाजन सहित) के सामान्य नियम है कि ऑपरेंड दोनों ही प्रकार के हैं, जिनमें से एक है में परिवर्तित हो जाएगा है । यदि दोनों ऑपरेटरों को उस सूची में प्रकार के प्रकार हैं, तो वे दोनों बाद में परिवर्तित हो जाएंगे। तो न तो है, वे दोनों तो अपने उदाहरण में int

    करने के लिए परिवर्तित कर दिया जाएगा:

    AverageUsage = (signed int)(TotalUsage - AverageUsage)/++incCount + AverageUsage 
    

    अगर incCountunsigned int, है तो अपने कलाकारों कोई प्रभाव नहीं है - घटाना पर हस्ताक्षर किए पूर्णांक में परिवर्तित हो जाएगा और फिर अनजान int पर वापस और एक हस्ताक्षरित विभाजन किया जाएगा। आपके द्वारा हस्ताक्षरित विभाजन चाहते हैं, आप की आवश्यकता होगी:

    AverageUsage = (int)(TotalUsage - AverageUsage)/(int)++incCount + AverageUsage 
    

    जो आप अगर incCount INT_MAX से अधिक मुसीबत में आप प्राप्त कर सकते हैं ध्यान दें के रूप में।

    सामान्य रूप से, विभाजन के लिए प्रोसेसर निर्देश केवल एक प्रकार निर्दिष्ट करते हैं, जिसका उपयोग दोनों ऑपरेटरों के लिए किया जाता है। जब अलग-अलग प्रकार के साथ विभाजन के लिए एक विशेष निर्देश होता है, तो आमतौर पर यह एक बड़ी (डबल चौड़ाई) लाभांश के लिए होता है, न कि एक अलग हस्ताक्षर।

    0

    यदि यह कुल उपयोग < औसत उपयोग के लिए पूर्वदर्शी और मान्य है, तो यह इन चरों के लिए हस्ताक्षर किए गए प्रकार के लिए पूरी तरह अनुचित है। TotalUsage < AverageUsage अर्थ होगा कि AverageUsage तो नकारात्मक हो सकता है (जो परिणाम हो सकता है अगर TotalUsage < AverageUsage। डेटा की जा रही 'औसतन' कभी नहीं नकारात्मक है, तो यह हिसाब से असंभव TotalUsage < AverageUsage के लिए है सच।

    यदि TotalUsage < औसत उपयोग मान्य नहीं है, तो इसके लिए सत्य होने के लिए आपके कोड या अंकगणित ओवरफ़्लो में कोई त्रुटि दिखाई देगी। आप उस संभावना के खिलाफ उस संभावना के खिलाफ सुरक्षा कर सकते हैं; शायद एक रिलीज निर्माण में हटाए गए मैक्रो के रूप में लागू किया गया है। यदि जोर दिया जाता है तो या तो इनपुट डेटा अमान्य था, या ओवरफ्लो हुआ, बाद के मामले में डेटा प्रकार बहुत छोटा है, और या तो long long, unsigned long long, या double उचित होगा।

    कास्टिंग के साथ भी, अगर कुल उपयोग < औसत उपयोग सत्य है तो अभिव्यक्ति का परिणाम अंकगणितीय रूप से नकारात्मक है, लेकिन आखिरकार एक हस्ताक्षरित प्रकार को असाइन किया गया है, इसलिए परिणाम अभी भी गलत होगा।

    अंतिम निष्कर्ष तब या तो कुल उपयोग < औसत उपयोग कभी भी सत्य नहीं हो सकता है, या आपके डेटा में अनुचित प्रकार है। समाधान लगभग निश्चित रूप से किसी प्रकार का कास्ट नहीं है।

    मेरी सलाह आम तौर पर पर परमाणुओं के लिए एक हस्ताक्षरित प्रकार का उपयोग करें, जिस पर अंकगणित किया जाएगा। ऐसा इसलिए है क्योंकि मिश्रित हस्ताक्षरित/हस्ताक्षरित अंकगणित की भाषा अर्थशास्त्र कुछ हद तक आर्केन और आसानी से गलत समझा जाता है, और क्योंकि मध्यवर्ती संचालन अन्यथा नकारात्मक मान उत्पन्न कर सकता है। भले ही चर के लिए ऋणात्मक मूल्य अर्थपूर्ण रूप से अर्थहीन है, फिर भी मैं उन सभी मामलों में हस्ताक्षरित प्रकारों के उपयोग की वकालत करता हूं जहां इस प्रकार की सकारात्मक सीमा अतिप्रवाह से बचने के लिए पर्याप्त बनी हुई है, और जहां यह पर्याप्त नहीं है। एक बड़े आकार का उपयोग करने के लिए जहां एक ही आकार के एक हस्ताक्षरित प्रकार का सहारा लेना संभव है। इसके अलावा, जहां हस्ताक्षरित प्रकारों पर अंकगणितीय परिचालन की आवश्यकता होती है, तो सभी ऑपरेटरों को हस्ताक्षर नहीं किया जाना चाहिए (शाब्दिक समेत), और कोई मध्यवर्ती ऑपरेशन के परिणामस्वरूप या अतिप्रवाह नहीं होना चाहिए।

    0

    क्या आपको सचमुच/रोलिंग-औसत की आवश्यकता है, या आप कुछ अन्य निम्न-पास फ़िल्टर का उपयोग कर सकते हैं? एक एकल-पोल (कभी-कभी "अल्फा" कहा जाता है) फिल्टर आप सूट हो सकता है:

    new_output = alpha * previous_output + (1-alpha)*new_input; 
    previous_output = new_output; 
    

    जहां alpha 0 और 0.9999

    के बीच ....

    करीब alpha 1 करने के लिए है, "धीमे" फिल्टर

    आप इसे आसानी से फ़्लोटिंग पॉइंट में या पूर्णतः पूर्णांक में पूर्ण कर सकते हैं।

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