2010-11-10 8 views
5

मुझे पता है कि आप मॉड्यूलस और विभाजन का उपयोग करके किसी संख्या के अंक प्राप्त कर सकते हैं। (Psuedocode इतनी के रूप में छात्रों को ऐसा करने उनके होमवर्क असाइनमेंट के लिए कुछ कार्य को पढ़ने बनाने के लिए):किसी संख्या के अंक प्राप्त करने के लिए कोई बेहतर विकल्प? (सी ++)

int pointer getDigits(int number) 
    initialize int pointer to array of some size 
    initialize int i to zero 
    while number is greater than zero 
     store result of number mod 10 in array at index i 
     divide number by 10 and store result in number 
     increment i 
    return int pointer 

वैसे ही कोई बेहतर है, मैं सोच रहा था निम्नलिखित कैसे मैंने पहले भी यह किया है है , इस कार्य को पूरा करने के लिए और अधिक कुशल तरीका? यदि नहीं, तो क्या किसी भी इस कार्य के लिए वैकल्पिक तरीके हैं, तारों के उपयोग से परहेज करते हैं? सी शैली या अन्यथा?

धन्यवाद। मैं पूछता हूं क्योंकि मैं इसे अपनी निजी परियोजना में करना चाहता हूं, और मैं इसे यथासंभव कुशलता से करना चाहता हूं।

कोई भी मदद और/या अंतर्दृष्टि की सराहना की जाती है।

+0

दोहराना div/mod वह सब कुछ है जो आप कर सकते हैं। यहां तक ​​कि sprintf() भी ऐसा करना है। – chrisaycock

+1

ओपी अलगो रिवर्स ऑर्डर में अंक नहीं देगा? – Chubsdad

उत्तर

3

अंकों को निकालने में लगने वाला समय सरणी को गतिशील रूप से आवंटित करने के लिए आवश्यक समय तक बौना जाएगा। एक struct में परिणाम लौटने पर विचार करें:

struct extracted_digits 
{ 
    int number_of_digits; 
    char digits[12]; 
}; 

आप (यहाँ 12 है, जो एक 32-बिट पूर्णांक के लिए पर्याप्त है) अंक की अधिकतम संख्या के लिए एक उपयुक्त मूल्य लेने के लिए चाहता हूँ। वैकल्पिक रूप से, आप std::array<char, 12> वापस कर सकते हैं और अमान्य मान का उपयोग करके टर्मिनल को एन्कोड कर सकते हैं (इसलिए, अंतिम मान के बाद, 10 या कुछ और जो अंक नहीं है) संग्रहीत करें।

चाहे आप नकारात्मक मूल्यों को संभालना चाहते हैं, इस पर निर्भर करते हुए, आपको यह भी तय करना होगा कि यून्री माइनस (-) की रिपोर्ट कैसे करें।

+0

+1 नकारात्मक के लिए ... – Anthony

+0

नकारात्मक भी सापेक्ष के व्यवहार को बदलने, तो तुरंत हस्ताक्षर –

3

जब तक आप 2 की शक्ति वाले आधार में संख्या का प्रतिनिधित्व नहीं करना चाहते हैं, तो यह करने का एकमात्र तरीका है।

1

"स्ट्रिंग्स के उपयोग से परहेज" करके, मुझे लगता है कि आप ऐसा कर रहे हैं क्योंकि स्ट्रिंग-केवल प्रतिनिधित्व बहुत अक्षम है यदि आप एक पूर्णांक मान चाहते हैं।

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

द्वारा "दोनों रूपों भंडारण", मेरा मतलब है आप की तरह एक संरचना है कर सकते हैं:

typedef struct { 
    int ival; 
    char sval[sizeof("-2147483648")]; // enough for 32-bits 
    int dirtyS; 
} tIntStr; 

और इस संरचना (या उसके पते) के बजाय पूर्णांक ही चारों ओर गुजरती हैं।

मैक्रो या की तरह इनलाइन कार्यों होने से:

inline void intstrSetI (tIntStr *is, int ival) { 
    is->ival = i; 
    is->dirtyS = 1; 
} 
inline char *intstrGetS (tIntStr *is) { 
    if (is->dirtyS) { 
     sprintf (is->sval, "%d", is->ival); 
     is->dirtyS = 0; 
    } 
    return is->sval; 
} 

फिर, मान सेट करने के लिए, आप का प्रयोग करेंगे:

tIntStr is; 
intstrSetI (&is, 42); 

और जब भी आप स्ट्रिंग प्रतिनिधित्व चाहता था:

printf ("%s\n" intstrGetS(&is)); 
fprintf (logFile, "%s\n" intstrGetS(&is)); 

यह आवश्यक होने पर स्ट्रिंग प्रस्तुति की गणना करने का लाभ है (ऊपरस्ट्रिंग प्रस्तुति और printf को केवल गंदे होने पर पुन: गणना करने की आवश्यकता नहीं होगी)।

यह एक समान चाल है जिसे मैं एसक्यूएल में प्रीकंप्यूटेड कॉलम और ट्रिगर्स का उपयोग करने के साथ उपयोग करता हूं। विचार यह है कि जब आवश्यक हो तो आप केवल गणना करते हैं। तो अनुक्रमित लोअरकेड अंतिम नाम को एक गणना/अद्यतन ट्रिगर के साथ गणना करने के लिए एक अतिरिक्त कॉलम, आमतौर पर select lower(non_lowercased_last_name) से बहुत अधिक कुशल है। ऐसा इसलिए है क्योंकि यह सभी पढ़ने में गणना (लिखने के समय पर किया गया) की लागत को कम करता है।

उस अर्थ में, यदि आपकी कोड प्रोफ़ाइल set-int/use-string/set-int/use-string... है तो इसका थोड़ा सा फायदा होता है। लेकिन, अगर यह set-int/use-string/use-string/use-string/use-string... है, तो आपको एक प्रदर्शन बढ़ावा मिलेगा।

यह अनुमान लगाया गया है कि कम से कम अतिरिक्त अतिरिक्त संग्रहण आवश्यक है, लेकिन अधिकांश प्रदर्शन समस्याएं अंतरिक्ष/समय व्यापार-बंद तक उबालती हैं।

और, यदि आप वास्तव में स्ट्रिंग से बचना चाहते हैं, तो आप अभी भी उसी विधि का उपयोग कर सकते हैं (केवल आवश्यकता होने पर गणना करें), यह केवल गणना है कि (गणना) संरचना अलग होगी।


एक अलग रूप में के रूप में: आप अच्छी तरह से पुस्तकालय कार्यों का उपयोग करने के अपने खुद के कोड handcrafting के बजाय यह करने के लिए कर सकते हैं। पुस्तकालय कार्यों को आम तौर पर अत्यधिक अनुकूलित किया जाएगा, संभवतः आपके कंपाइलर से आपके कोड से बना सकते हैं (हालांकि यह निश्चित रूप से गारंटी नहीं है)।

यह भी संभावना है कि itoa, यदि आपके पास कोई है, तो संभवतः sprintf("%d") से भी अधिक सीमित होगा, इसके सीमित उपयोग मामले को देखते हुए। हालांकि, आपको उपाय करना चाहिए, अनुमान नहीं! पुस्तकालय कार्यों के संदर्भ में नहीं, बल्कि यह संपूर्ण समाधान (और अन्य) भी।

1

समयपूर्व अनुकूलन के स्मैक। यदि प्रोफाइलिंग यह मायने रखती है, तो अपने अहंकार को इसके साथ तुलना करना सुनिश्चित करें - आंतरिक रूप से यह कुछ CPU निर्देशों का उपयोग कर सकता है जिनके पास आपके पास C++ से स्पष्ट पहुंच नहीं है, और आपके कंपाइलर का ऑप्टिमाइज़र नियोजित करने के लिए पर्याप्त चालाक नहीं हो सकता है (उदाहरण के लिए आम , जो मॉड परिणाम सहेजते समय divs)। प्रयोग (और बेंचमार्क) स्वयं को असेंबलर कोडिंग। आप आईटीओए के असेंबली कार्यान्वयन के लिए खुदाई कर सकते हैं (जो कि आप जो मांग रहे हैं उसके समान नहीं है, लेकिन इष्टतम सीपीयू निर्देशों का सुझाव दे सकता है)।

+0

टिप्पण के बाद निरपेक्ष मान ले कार्यों div(), ldiv() और lldiv की जाँच करना चाहिए()। वे दोनों कोटेन्ट और शेष दोनों लौटते हैं और लगभग हमेशा मशीन कोड में अनुकूलित करते हैं। –

+0

अपडेट किया गया: मुझे लगता है कि वे अनुकूलित सोचा लेकिन 86 पर यह नहीं दिखाई देता है। –

+0

@ ज़ेन लिंक्स: दिलचस्प बिंदु - आप निश्चित रूप से आशा करते हैं कि यदि वे उपलब्ध हों तो वे असेंबली का उपयोग करेंगे, हालांकि आप प्रत्येक शब्द-आकार कुशल थे, लेकिन यह जानने के लिए कि मेरे अनुभव में महत्वपूर्ण रूप से यह एक डीबगर में प्रत्येक को जांचना चाहेगा जीसीसी वे इनलाइन नहीं हैं और यह किसी भी प्रदर्शन लाभ को अच्छी तरह से खत्म कर सकता है: -। –

1

हां, एक और अधिक प्रभावी तरीका है, लेकिन पोर्टेबल नहीं है। इंटेल के एफपीयू में एक विशेष बीसीडी प्रारूप संख्या है। इसलिए, आपको केवल संवाददाता असेंबलर निर्देश को कॉल करना है जो एसटी (0) को बीसीडी प्रारूप में परिवर्तित करता है और परिणाम को स्मृति में संग्रहीत करता है। निर्देश का नाम FBSTP है।

1

यह देखने के लिए काफी मामूली है कि "अंक" 00 - 99 का उपयोग करके बेस-100 समाधान भी काम कर सकता है। प्रत्येक यात्रा में, आप एक %100 इस तरह के एक अंकों जोड़ी का उत्पादन करने, इस प्रकार चरणों की संख्या को आधा करने करना चाहते हैं। दुविधा यह है कि अपने अंकों तालिका अब है बजाय 10 फिर भी, यह आसानी से एल 1 कैश में फिट बैठता है की 200 बाइट (जाहिर है, यह केवल लागू होता है अगर आप संख्या की एक बहुत कुछ परिवर्तित कर रहे हैं, लेकिन अन्यथा efficientcy वैसे भी विवादास्पद है)। साथ ही, आप एक अग्रणी शून्य के साथ समाप्त हो सकते हैं, जैसा कि "0128" में है।

0

गणितीय तौर पर, एक पूर्णांक के दशमलव अंकों की संख्या 1+int(log10(abs(a)+1))+(a<0); है।

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

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