पूर्णांक में अंकों की संख्या निर्धारित करने का कुशल तरीका


144

यह निर्धारित करने का एक बहुत ही कुशल तरीका है कि C ++ में एक पूर्णांक में कितने अंक हैं?


11
किस बेस में? 2? 10?
जैकब क्राल

2
मैं इसे बेस 10 में करना चाहूंगा
सेठ

1
मैंने एक बार संबंधित प्रश्न पूछा था: आप इंट में पहला अंक कैसे प्राप्त कर सकते हैं? नीचे दी गई कई समान पद्धतियों का लोगों के उत्तरों में उपयोग किया गया था। इस मामले में यह लिंक आपके कार्य के लिए प्रासंगिक है [ stackoverflow.com/questions/701322/]
दीना

क्या इनलाइन असेंबली योग्य है?
ग्योर्गी एंड्रेसेक

1
जबकि ये सभी उत्तर आधार 10 के संदर्भ में हैं, किसी भी वांछित आधार के लिए परिणाम की गणना करने के लिए बदलना बहुत आसान है।
इरा बैक्सटर

जवाबों:


106

खैर, सबसे कुशल तरीका है, मान लीजिए कि आप पूर्णांक के आकार को जानते हैं, तो यह एक खोज होगी। बहुत छोटे लॉगरिदम आधारित दृष्टिकोण से तेज होना चाहिए। यदि आप '-' की गिनती के बारे में परवाह नहीं करते हैं, तो + 1 को हटा दें।

// generic solution
template <class T>
int numDigits(T number)
{
    int digits = 0;
    if (number < 0) digits = 1; // remove this line if '-' counts as a digit
    while (number) {
        number /= 10;
        digits++;
    }
    return digits;
}

// partial specialization optimization for 32-bit numbers
template<>
int numDigits(int32_t x)
{
    if (x == MIN_INT) return 10 + 1;
    if (x < 0) return numDigits(-x) + 1;

    if (x >= 10000) {
        if (x >= 10000000) {
            if (x >= 100000000) {
                if (x >= 1000000000)
                    return 10;
                return 9;
            }
            return 8;
        }
        if (x >= 100000) {
            if (x >= 1000000)
                return 7;
            return 6;
        }
        return 5;
    }
    if (x >= 100) {
        if (x >= 1000)
            return 4;
        return 3;
    }
    if (x >= 10)
        return 2;
    return 1;
}

// partial-specialization optimization for 8-bit numbers
template <>
int numDigits(char n)
{
    // if you have the time, replace this with a static initialization to avoid
    // the initial overhead & unnecessary branch
    static char x[256] = {0};
    if (x[0] == 0) {
        for (char c = 1; c != 0; c++)
            x[c] = numDigits((int32_t)c);
        x[0] = 1;
    }
    return x[n];
}

5
शायद मेरे जवाब की तुलना में तेजी से, अच्छी तरह से किया। अतिरिक्त दक्षता के लिए, यदि आप जानते हैं कि आपके इनपुट नंबर ज्यादातर छोटे होंगे (मैं 100,000 से कम अनुमान लगा रहा हूं), तो परीक्षणों को उल्टा करें: अगर (x <10) वापसी 1; अगर (x <100) वापसी 2; आदि, ताकि फ़ंक्शन कम परीक्षण करेगा और तेजी से बाहर निकल जाएगा।
स्क्वेलार्ट

29
या शायद फिर से बयान और घोंसला अगर बयान, एक रैखिक खोज के बजाय एक द्विआधारी खोज करने के लिए।
dave4420

1
यह एक अच्छा विचार नहीं है। क्या होता है जब आर्किटेक्चर 256 बिट पूर्णांक तक फैलता है। आपको वापस आने और इस कोड को संशोधित करने के लिए याद रखना होगा। वास्तविक जीवन में ऐसा नहीं होगा और चूहे यह शायद सही आकार के बफर का निर्माण करने के लिए उपयोग करने जा रहे हैं जो अब आप बड़े वास्तुकारों पर चलने वाली समस्याओं पर बफर के सभी प्रकारों के लिए खुद को खोल रहे हैं।
मार्टिन

3
संख्याओं का एक समान वितरण मानते हुए, रिवर्स लीनियर खोज (अधिकतम अंकों से 1 तक) द्विआधारी खोज की तुलना में औसतन तेज हो सकती है क्योंकि N-1 अंकों वाले ग्राफिक्स.stanford.edu/~ की
पिता।

6
मैं 256 या 128 बिट पूर्णांक के बारे में बहुत कठिन चिंता नहीं करूंगा। जब तक आपको ब्रह्माण्ड में इलेक्ट्रॉनों की संख्या गिनने की जरूरत नहीं है (10 ^ 78 पिछली बार जब मैंने ऐसा किया था), 64 बिट्स बहुत अच्छा करेंगे। 32 बिट मशीनें ~ 15 साल तक चलीं। मुझे लगता है कि 64 बिट मशीनें बहुत लंबे समय तक चलेंगी। बड़ी संख्या के लिए, मल्टीप्रेशर अंकगणित ठीक हो जाएगा, और मुझे संदेह है कि क्या कंप्यूटिंग काउंट की दक्षता मायने रखेगी।
इरा बैक्सटर

74

सबसे सरल तरीका है:

unsigned GetNumberOfDigits (unsigned i)
{
    return i > 0 ? (int) log10 ((double) i) + 1 : 1;
}

log10 में परिभाषित किया गया है <cmath>या<math.h> । यह देखने के लिए आपको यह देखना होगा कि क्या यह यहां पोस्ट किए गए अन्य लोगों की तुलना में तेज़ है। मुझे यकीन नहीं है कि फ्लोटिंग पॉइंट सटीक के संबंध में यह कितना मजबूत है। इसके अलावा, तर्क नकारात्मक मानों के रूप में अहस्ताक्षरित है और लॉग वास्तव में मिश्रण नहीं करते हैं।


7
32 बिट इनट्स और 56 बिट फ्लोट्स के लिए, यह संभवतः काम करता है। यदि इनपुट लंबा (64 बिट्स) है, तो 56-बिट्स डबल-प्रिसिजन लॉग के कारण 10 ^ n के बड़े मानों के पास मानों के मामलों में गलत उत्तर उत्पन्न हो सकता है। 2 ^ 50 से ऊपर की परेशानी की अपेक्षा करें।
इरा बैक्सटर

1
लॉग फ़ंक्शंस कितने सही हैं, इसका भी सवाल है। मैंने जाँच नहीं की है कि वे आधुनिक पुस्तकालयों में कितने सही हैं, और एक बिलियन में एक हिस्से के लिए अच्छा होने का भरोसा करते हुए आँख बंद करके आरामदायक नहीं होंगे।
डेविड थॉर्नले

@DavidThornley: लॉग या अन्य गणित फ़ंक्शन कंपाइलर कमांड लाइन पर निर्दिष्ट किए जाने तक पूरी तरह से सटीक हैं। कुछ संकलन समय पर x86 आंतरिक में परिवर्तित हो जाएंगे। कुछ मौजूद नहीं हैं और मौजूदा आंतरिक के सूत्रों में विस्तार होगा। उदाहरण के लिए यदि -fpfastआप x87 के बजाय SSE इंस्ट्रिक्टिक्स का उपयोग देख सकते हैं, जो सटीक IIRC पर कम गारंटी देता है। लेकिन डिफ़ॉल्ट रूप से कोई समस्या नहीं है।
v.oddou

@DavidThornley: यह सटीक से अधिक है। सवाल यह है कि यह गारंटी है या नहीं कि log10 (10 ^ k) ≥ k सभी प्रासंगिक कश्मीर के लिए। यह गारंटी है कि किसी भी अपरिहार्य दौर त्रुटि सही दिशा में चला जाता है। k + eps परिणामस्वरूप काम करता है, k - eps नहीं करता है। और "बिल्कुल सटीक" भोला है।
gnasher729

1
परीक्षण i> 0 को i> 9
Pat

60

शायद मैंने इस सवाल को गलत समझा लेकिन क्या ऐसा नहीं होता?

int NumDigits(int x)  
{  
    x = abs(x);  
    return (x < 10 ? 1 :   
        (x < 100 ? 2 :   
        (x < 1000 ? 3 :   
        (x < 10000 ? 4 :   
        (x < 100000 ? 5 :   
        (x < 1000000 ? 6 :   
        (x < 10000000 ? 7 :  
        (x < 100000000 ? 8 :  
        (x < 1000000000 ? 9 :  
        10)))))))));  
}  

29
और मुझे आश्चर्य नहीं होगा अगर यह समाधान सबसे तेज़ होगा।
VisioN

32
int digits = 0; while (number != 0) { number /= 10; digits++; }

नोट: "0" में 0 अंक होंगे! यदि आपको 1 अंक प्राप्त करने के लिए 0 की आवश्यकता है, तो उपयोग करें:

int digits = 0; do { number /= 10; digits++; } while (number != 0);

(धन्यवाद केविन फेगन)

अंत में, यह जानने के लिए एक प्रोफाइलर का उपयोग करें कि आपके मशीन पर यहां कौन से उत्तर तेजी से होंगे ...


3
यह अनियंत्रित लूप दृष्टिकोण की तुलना में तेज हो सकता है या नहीं हो सकता है - आपको अंतर को प्रोफाइल करना होगा (लंबे समय में नगण्य होना चाहिए)।
विटाली

सहमत, रूपरेखा वास्तव में सुनिश्चित करने का एकमात्र तरीका है! मैंने उस टिप्पणी के साथ अपना उत्तर अपडेट किया, क्योंकि बेन एस की छत (लॉग 10 ()) उत्तर गायब हो गया है।
स्क्वेलार्ट

11

व्यावहारिक मजाक: यह सबसे कारगर तरीका (अंकों की संख्या संकलन समय पर गणना की जाती है):

template <unsigned long long N, size_t base=10>
struct numberlength
{
    enum { value = 1 + numberlength<N/base, base>::value };
};

template <size_t base>
struct numberlength<0, base>
{
    enum { value = 0 };
};

स्वरूपण, इनपुट तत्वों आदि में संख्या क्षेत्र के लिए आवश्यक चौड़ाई निर्धारित करने के लिए उपयोगी हो सकता है।


4
सबसे पहले, आपका समाधान 0. के लिए काम नहीं करता है। दूसरा आपके समाधान एक चर के सामान्य मामले के लिए अनुपयुक्त है। तीसरा, यदि आप एक निरंतर शाब्दिक उपयोग कर रहे हैं, तो आप पहले से ही जानते हैं कि इसके कितने अंक हैं।
विटाली

यह 0 के लिए भी काम करता है। यह किसी भी आधार के लिए काम करता है। बाकी वैध बिंदु हैं जिन्हें मैंने पहले ही रेखांकित किया है।
blinnov.com

3
मुझे नहीं लगता कि यह वास्तव में है। यह 0आधार पर विफल रहता है और आधार पर भी विफल रहता है 1:) और आधार के रूप में दिए जाने पर शून्य त्रुटियों से विभाजित करता है 0। हालांकि इसे ठीक किया जा सकता है। वैसे भी मैं एक बहुत पुरानी पोस्ट पर नाइटपैकिंग कर रहा हूं, इसलिए क्षमा करें, यह सिर्फ इतना है कि मुझे लगता है कि यह एक मजाक नहीं है और वास्तव में उपयोगी हो सकता है।
tjm

9

आपके द्वारा स्वीकृत उत्तर के बहुत छोटे संस्करण के लिए बिट ट्विडलिंग हैक्स देखें । यदि आपके इनपुट को सामान्य रूप से वितरित किया जाता है, तो इसका उत्तर खोजने का लाभ जल्द ही होता है, पहले बड़े स्थिरांक की जांच करके। (v >= 1000000000)76% मूल्यों को पकड़ता है, इसलिए यह जांचना कि पहले औसतन तेज होगा।


यह स्पष्ट नहीं है कि बिट-ट्विडलिंग वास्तव में तेज है या नहीं। सबसे खराब स्थिति में भी, मेरे संशोधित दृष्टिकोण में 4 तुलनाओं की आवश्यकता होती है (यदि मैं आगे विभाजन की जांच करता हूं तो यह 3 तक ले जाने में सक्षम हो सकता है, हालांकि यह संभावना नहीं दिखता है)। मुझे गंभीरता से संदेह है कि यह अंकगणितीय संचालन + मेमोरी लोड द्वारा हरा दिया जा रहा है (हालांकि यदि पर्याप्त रूप से एक्सेस किया जाता है, तो वे सीपीयू कैश में गायब हो जाते हैं)। याद रखें, उनके द्वारा दिए गए उदाहरण में, वे लॉग बेस 2 को कुछ सार IntegerLogBase2 फ़ंक्शन के रूप में भी छिपाते हैं (जो स्वयं वास्तव में सस्ता नहीं है)।
विटाली

बस एक अनुवर्ती के रूप में, यदि संख्या सामान्य रूप से वितरित की जाती है, तो इन-ऑर्डर चेक करना अधिक तेज़ है। हालांकि, यह सबसे खराब स्थिति में दो बार धीमा होने का पतित मामला है। इनपुट स्थान के बजाय अंकों की संख्या से विभाजित दृष्टिकोण का मतलब है कि व्यवहार में एक पतित मामला नहीं है और हमेशा आशावादी प्रदर्शन करता है। इसके अलावा, याद रखें कि आप यह धारणा बना रहे हैं कि संख्या समान रूप से वितरित की जाएगी। वास्तव में, वे <a href=" en.wikipedia.org/wiki/…> से संबंधित कुछ वितरण का अनुसरण करने की अधिक संभावना रखते हैं, मेरा अनुमान होगा।
विटाली

बिट ट्विडलिंग हैक ऊपर विभाजन विधि से अधिक तेज़ नहीं हैं, लेकिन वे संभावित रूप से दिलचस्प हैं यदि आपके पास यहां फ़्लोटिंग की तरह अधिक सामान्य मामला था।
कॉर्विन जॉय सेप

1
बिट ट्विगलिंग हैक इंट लॉग 2 को देखते हुए, इंट लॉग 10 प्राप्त करने का एक तरीका बताता है। यह int log2 पाने के लिए कई तरीके सुझाता है, जिनमें ज्यादातर कुछ तुलना / शाखाएं शामिल हैं। (मुझे लगता है कि आप अप्रत्याशित शाखाओं, विटाली की लागत को कम कर रहे हैं)। यदि आप इनलाइन x86 asm का उपयोग कर सकते हैं, तो BSR निर्देश आपको वैल्यू का int log2 देगा (यानी सबसे महत्वपूर्ण सेट बिट का बिट इंडेक्स)। यह K8 (10 चक्र विलंबता) पर थोड़ा धीमा है, लेकिन कोर 2 (2 या 3 चक्र विलंबता) पर तेज़ है। K8 पर भी, तुलनाओं की तुलना में अच्छी तरह से तेज हो सकता है।
पीटर कॉर्ड्स

K10 पर, lzcnt अग्रणी शून्य को गिनता है, इसलिए यह लगभग bsr के समान है, लेकिन 0 का इनपुट अब अपरिभाषित परिणामों के साथ एक विशेष मामला नहीं है। अक्षांश: BSR: 4, LZCNT: 2.
पीटर कॉर्ड्स

8

स्ट्रिंग में कनवर्ट करें और फिर अंतर्निहित कार्यों का उपयोग करें

unsigned int i;
cout<< to_string(i).length()<<endl;

7
int x = 1000;
int numberOfDigits = x ? static_cast<int>(log10(abs(x))) + 1 : 1;

3
हालांकि यह LOCs के संदर्भ में कुशल है, जैसा कि लॉग के स्वीकृत उत्तर उपयोग में नोट किया गया है, संभवतः सर्वश्रेष्ठ प्रदर्शन नहीं देगा।
इयान

@ इयान क्यों नहीं? यह केवल FPU निर्देशों की एक जोड़ी है। सभी शाखाओं की तुलना में बेहतर मील और अन्य उत्तरों में लूप।
लोर्ने

5

पिछले पोस्टर ने एक लूप का सुझाव दिया था जो 10. से विभाजित होता है। चूंकि आधुनिक मशीनों पर गुणन बहुत तेज़ हैं, मैं इसके बजाय निम्नलिखित कोड सुझाऊंगा:

 int digits = 1, pten=10; while ( pten <= number ) { digits++; pten*=10; }

1
शैतान विवरण में है - क्या कहता है std :: न्यूमेरिक_लिमिट्स <int> :: max == संख्या - यह समाप्त होने में समस्या हो सकती है
pgast

2
यदि आप उस मामले के बारे में चिंतित हैं, तो आप बहुत बड़े मूल्यों को संभालने के लिए एक अतिरिक्त IF जोड़ सकते हैं।
इरा बैक्सटर

2
मुझे यह देखना चाहिए कि x86 मशीनों पर, इस मामले में उपयोग किए जाने वाले एक स्थिर 10 द्वारा गुणा, वास्तव में संकलक द्वारा LEA R2, [8 * R1 + R1], ADD R1, R2 के रूप में कार्यान्वित किया जा सकता है, इसलिए यह 2 घड़ियों को अधिकतम लेता है। चर के गुणक दसियों घड़ियां लेते हैं, और विभाजन बहुत खराब होते हैं।
इरा बैक्सटर

विभाजित दृष्टिकोण के साथ लाभ यह है कि आपको नकारात्मक संख्याओं के बारे में चिंता करने की आवश्यकता नहीं है।
जोहान्स शाउब -

1
मैंने डिवीजन दृष्टिकोण बनाम मल्टीप्लस एप्रोच (साइन इश्यू को हटाने के लिए एक फेबस के साथ) बेंचमार्क किया। मेरी मशीन पर विभाजन दृष्टिकोण गुणन दृष्टिकोण की तुलना में कारक 2 धीमा है। यह समयपूर्व अनुकूलन है या नहीं, वास्तव में इस बात पर निर्भर करता है कि इसे कहाँ और कैसे कहा जाता है।
Spacemoose

5

पीपीसी आर्किटेक्चर के पास थोड़ी गिनती का निर्देश है। उसके साथ, आप एक निर्देश में एक धनात्मक पूर्णांक के लॉग बेस 2 को निर्धारित कर सकते हैं। उदाहरण के लिए, 32 बिट होगा:

#define log_2_32_ppc(x) (31-__cntlzw(x))

यदि आप बड़े मानों पर त्रुटि के एक छोटे से मार्जिन को संभाल सकते हैं तो आप इसे कुछ अन्य निर्देशों के साथ आधार 10 में लॉग इन कर सकते हैं:

#define log_10_estimate_32_ppc(x) (9-(((__cntlzw(x)*1233)+1545)>>12))

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

मैं केवल हाथ से पीपीसी निर्देशों को जानता हूं, लेकिन अन्य आर्किटेक्चर के समान निर्देश होने चाहिए।


यह समाधान log2 (15) = 4 बिट्स और log2 (9) = 4 बिट्स की गणना करता है। लेकिन मुद्रित करने के लिए 15 और 9 को दशमलव अंकों की विभिन्न संख्याओं की आवश्यकता होती है। इसलिए यह तब तक काम नहीं करता है, जब तक कि आप कभी-कभी बहुत से अंकों के साथ अपने नंबरों को प्रिंट करने का मन नहीं बनाते हैं। लेकिन उस मामले में, आप हमेशा "10" चुन सकते हैं इंट के जवाब के रूप में।
इरा बैक्सटर

वाह, एक अनुमानित फ़ंक्शन। अच्छा लगा।
डग ६५५३६

4
 #include <iostream>
 #include <math.h>

 using namespace std;

 int main()
 {
     double num;
     int result;
     cout<<"Enter a number to find the number of digits,  not including decimal places: ";
     cin>>num;
     result = ((num<=1)? 1 : log10(num)+1);
     cout<<"Number of digits "<<result<<endl;
     return 0;
 }

यह संभवतः आपकी समस्या को हल करने का सबसे सरल तरीका है, यह मानते हुए कि आप दशमलव से पहले केवल अंकों की परवाह करते हैं और 10 से कम किसी भी चीज़ को केवल 1 अंक मानते हैं।


1

मुझे इरा बाक्सटर का जवाब पसंद है। यहां एक टेम्प्लेट वेरिएंट है जो विभिन्न आकारों को संभालता है और अधिकतम पूर्णांक मानों (लूप से बाहर की ओर ऊपरी बाउंड चेक को फहराने के लिए अद्यतन) से संबंधित है:

#include <boost/integer_traits.hpp>

template<typename T> T max_decimal()
{
    T t = 1;

    for (unsigned i = boost::integer_traits<T>::digits10; i; --i)
        t *= 10;

    return t;
}

template<typename T>
unsigned digits(T v)
{
    if (v < 0) v = -v;

    if (max_decimal<T>() <= v)
        return boost::integer_traits<T>::digits10 + 1;

    unsigned digits = 1;
    T boundary = 10;

    while (boundary <= v) {
        boundary *= 10;
        ++digits;
    }

    return digits;
}

वास्तव में अतिरिक्त परीक्षण को लूप से बाहर निकालने से बेहतर प्रदर्शन प्राप्त करने के लिए, आपको अपने मंच पर प्रत्येक प्रकार के लिए स्थिरांक वापस करने के लिए max_decimal () को विशेषज्ञ बनाने की आवश्यकता है। पर्याप्त रूप से मैजिक कंपाइलर कॉल को max_decimal () को एक निरंतरता में अनुकूलित कर सकता है, लेकिन आज अधिकांश कंपाइलरों के साथ विशेषज्ञता बेहतर है। जैसा कि यह खड़ा है, यह संस्करण संभवतः धीमा है क्योंकि लूप से निकाले गए परीक्षणों की तुलना में मैक्सिममडिमल की लागत अधिक है।

मैं पाठक के लिए एक अभ्यास के रूप में वह सब छोड़ दूँगा।


आप ऊपरी सीमा की जाँच करना चाहते हैं एक अलग सशर्त पहले जाँच की ताकि आप इसे प्रत्येक लूप पुनरावृत्ति पर जाँच न करें।
इरा बैक्सटर

आप उस अस्थायी टी में 10 नहीं डालना चाहते हैं। कंपाइलर टी को गुणा करके वास्तविक चर से गुणा करने पर विचार कर सकता है, और सामान्य उद्देश्य को गुणा निर्देश का उपयोग कर सकता है। यदि आपने इसके बजाय "परिणाम * = 10" लिखा है; संकलक निश्चित रूप से लगातार 10 से गुणा को नोटिस करेगा और इसे कुछ पारियों और जोड़ के साथ लागू करेगा, जो कि बहुत तेज है।
इरा बैक्सटर

यदि टी द्वारा गुणन हमेशा 10 से गुणा किया जाता है, तो हाँ, संकलक शक्ति में कमी कर सकता है। हालाँकि, इस मामले में t लूप-इनवेरिएंट नहीं है (यह एक पूर्णांक पावर फ़ंक्शन का एक संशोधन है जो मैंने चारों ओर पड़ा था)। सही अनुकूलन एक स्थिर रिटर्न प्रकार पर विशेषज्ञता है। हालाँकि, आप सही हैं कि, इस मामले में, फ़ंक्शन हमेशा 10 पावर तक बढ़ा रहा है, न कि किसी पावर के लिए एक मनमाना पूर्णांक, और ताकत में कमी एक अच्छी जीत देती है। इसलिए मैंने एक बदलाव किया ... इस बार और बदलाव वास्तव में एक अभ्यास के रूप में बाकी हैं! (स्टैक ओवरफ्लो एक बड़ा टाइम सिंक है ...)
जानम

1
#include <stdint.h> // uint32_t [available since C99]

/// Determine the number of digits for a 32 bit integer.
/// - Uses at most 4 comparisons.
/// - (cX) 2014 adolfo.dimare@gmail.com
/// - \see http://stackoverflow.com/questions/1489830/#27669966
/**  #d == Number length vs Number of comparisons == #c
     \code
         #d | #c   #d | #c
         ---+---   ---+---
         10 | 4     5 | 4
          9 | 4     4 | 4
          8 | 3     3 | 3
          7 | 3     2 | 3
          6 | 3     1 | 3
     \endcode
*/
unsigned NumDigits32bs(uint32_t x) {
    return // Num-># Digits->[0-9] 32->bits bs->Binary Search
    ( x >= 100000u // [6-10] [1-5]
    ?   // [6-10]
        ( x >= 10000000u // [8-10] [6-7]
        ?   // [8-10]
            ( x >= 100000000u // [9-10] [8]
            ? // [9-10]
                ( x >=  1000000000u // [10] [9]
                ?   10
                :    9
                )
            : 8
            )
        :   // [6-7]
            ( x >=  1000000u // [7] [6]
            ?   7
            :   6
            )
        )
    :   // [1-5]
        ( x >= 100u // [3-5] [1-2]
        ?   // [3-5]
            ( x >= 1000u // [4-5] [3]
            ? // [4-5]
                ( x >=  10000u // [5] [4]
                ?   5
                :   4
                )
            : 3
            )
        :   // [1-2]
            ( x >=  10u // [2] [1]
            ?   2
            :   1
            )
        )
    );
}

0

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

#include <limits>
#include <type_traits>
#include <array>

template <class T> 
size_t NumberOfDecPositions ( T v, typename std::enable_if<std::is_unsigned<T>::value>::type* = 0 )
{
    typedef std::array<T,std::numeric_limits<T>::digits10+1> array_type;
    static array_type powers_of_10;
    if ( powers_of_10.front() == 0 )
    {
        T n = 1;
        for ( T& i: powers_of_10 )
        {
            i = n;
            n *= 10;
        }
    }

    size_t l = 0, r = powers_of_10.size(), p;
    while ( l+1 < r )
    {
        p = (l+r)/2;
        if ( powers_of_10[p] <= v )
            l = p;
        else
            r = p;
    }
    return l + 1;
};

template <class T> 
size_t NumberOfDecPositions ( T v, typename std::enable_if<std::is_signed<T>::value>::type* = 0 )
{
    typedef typename std::make_unsigned<T>::type unsigned_type;
    if ( v < 0 )
        return NumberOfDecPositions ( static_cast<unsigned_type>(-v) ) + 1;
    else
        return NumberOfDecPositions ( static_cast<unsigned_type>(v) );
}

यदि किसी को और अधिक अनुकूलन की परवाह है, तो कृपया ध्यान दें कि शक्तियों के पहले तत्व सरणी का उपयोग कभी नहीं किया जाता है, और 2 बार lदिखाई देता है +1


0

अंकों की संख्या और प्रत्येक अंक की स्थिति के मूल्य की आवश्यकता होती है।

int64_t = number, digitValue, digits = 0;    // or "int" for 32bit

while (number != 0) {
    digitValue = number % 10;
    digits ++;
    number /= 10;
}

digitआपको वर्तमान में लूप में संसाधित किए गए संख्या पद पर मूल्य देता है। उदाहरण के लिए संख्या 1776 के लिए अंक मान है:
6 में 1 लूप
7 में 2 लूप
7 में, 3 में
1 लूप में 4 लूप में 1


0
// Meta-program to calculate number of digits in (unsigned) 'N'.    
template <unsigned long long N, unsigned base=10>
struct numberlength
{   // http://stackoverflow.com/questions/1489830/
    enum { value = ( 1<=N && N<base ? 1 : 1+numberlength<N/base, base>::value ) };
};

template <unsigned base>
struct numberlength<0, base>
{
    enum { value = 1 };
};

{
    assert( (1 == numberlength<0,10>::value) );
}
assert( (1 == numberlength<1,10>::value) );
assert( (1 == numberlength<5,10>::value) );
assert( (1 == numberlength<9,10>::value) );

assert( (4 == numberlength<1000,10>::value) );
assert( (4 == numberlength<5000,10>::value) );
assert( (4 == numberlength<9999,10>::value) );

ऊपर 'ब्लिनोव डॉट कॉम' से "प्रैक्टिकल जोक" के लिए सुधार
एडोल्फो

0
/// Determine the number of digits for a 64 bit integer.
/// - Uses at most 5 comparisons.
/// - (cX) 2014 adolfo.dimare@gmail.com
/// - \see http://stackoverflow.com/questions/1489830/#27670035
/**  #d == Number length vs Number of comparisons == #c
     \code
         #d | #c   #d | #c     #d | #c   #d | #c
         ---+---   ---+---     ---+---   ---+---
         20 | 5    15 | 5      10 | 5     5 | 5
         19 | 5    14 | 5       9 | 5     4 | 5
         18 | 4    13 | 4       8 | 4     3 | 4
         17 | 4    12 | 4       7 | 4     2 | 4
         16 | 4    11 | 4       6 | 4     1 | 4
     \endcode
*/
unsigned NumDigits64bs(uint64_t x) {
    return // Num-># Digits->[0-9] 64->bits bs->Binary Search
    ( x >= 10000000000ul // [11-20] [1-10]
    ?
        ( x >= 1000000000000000ul // [16-20] [11-15]
        ?   // [16-20]
            ( x >= 100000000000000000ul // [18-20] [16-17]
            ?   // [18-20]
                ( x >= 1000000000000000000ul // [19-20] [18]
                ? // [19-20]
                    ( x >=  10000000000000000000ul // [20] [19]
                    ?   20
                    :   19
                    )
                : 18
                )
            :   // [16-17]
                ( x >=  10000000000000000ul // [17] [16]
                ?   17
                :   16
                )
            )
        :   // [11-15]
            ( x >= 1000000000000ul // [13-15] [11-12]
            ?   // [13-15]
                ( x >= 10000000000000ul // [14-15] [13]
                ? // [14-15]
                    ( x >=  100000000000000ul // [15] [14]
                    ?   15
                    :   14
                    )
                : 13
                )
            :   // [11-12]
                ( x >=  100000000000ul // [12] [11]
                ?   12
                :   11
                )
            )
        )
    :   // [1-10]
        ( x >= 100000ul // [6-10] [1-5]
        ?   // [6-10]
            ( x >= 10000000ul // [8-10] [6-7]
            ?   // [8-10]
                ( x >= 100000000ul // [9-10] [8]
                ? // [9-10]
                    ( x >=  1000000000ul // [10] [9]
                    ?   10
                    :    9
                    )
                : 8
                )
            :   // [6-7]
                ( x >=  1000000ul // [7] [6]
                ?   7
                :   6
                )
            )
        :   // [1-5]
            ( x >= 100ul // [3-5] [1-2]
            ?   // [3-5]
                ( x >= 1000ul // [4-5] [3]
                ? // [4-5]
                    ( x >=  10000ul // [5] [4]
                    ?   5
                    :   4
                    )
                : 3
                )
            :   // [1-2]
                ( x >=  10ul // [2] [1]
                ?   2
                :   1
                )
            )
        )
    );
}

0

पूर्णांक 'X' के लिए आप किसी भी लूप का उपयोग किए बिना अंकों की संख्या जानना चाहते हैं, यह समाधान केवल एक पंक्ति में एक सूत्र में कार्य करता है इसलिए यह सबसे इष्टतम समाधान है जो मैंने कभी इस समस्या को देखा है।

 int x = 1000 ; 
 cout<<numberOfDigits = 1+floor(log10(x))<<endl ; 

INT_MAX के लिए और भी नकारात्मक संख्या के लिए विफल।
रानू

INTANMAX के लिए @ranu विफल कैसे? जब तर्क में परिवर्तित किया जाता है double? या क्या आप INT_MAX दशमलव अंकों के साथ कुछ असंभव पूर्णांक इनपुट की बात कर रहे हैं? जो यहां भी हर दूसरे जवाब में विफल होगा?
लोर्ने

0
int numberOfDigits(int n){

    if(n<=9){
        return 1;
    }
    return 1 + numberOfDigits(n/10);
}

यह वही है जो मैं करूंगा, यदि आप इसे आधार के लिए चाहते हैं 10. बहुत तेज़ है और आप पूरी तरह से स्टैक ओवरफ्लॉक खरीदेंगे जो पूर्णांक खरीदेंगे


0
int num,dig_quant = 0;
cout<<"\n\n\t\t--Count the digits in Number--\n\n";
cout<<"Enter Number: ";
cin>>num;
for(int i = 1; i<=num; i*=10){
    if(num / i  > 0){
      dig_quant += 1;
    }
}
 cout<<"\n"<<number<<" include "<<dig_quant<<" digit"
 cout<<"\n\nGoodbye...\n\n";

0

यदि तेजी से अधिक कुशल है, तो यह andrei alexandrescu के सुधार में सुधार है । उसका संस्करण पहले से ही भोले तरीके (हर अंक पर 10 से भाग) से तेज था। नीचे दिया गया संस्करण निरंतर समय है और सभी आकारों के लिए x86-64 और ARM पर कम से कम तेजी से है, लेकिन दो बार बाइनरी कोड के रूप में है, इसलिए यह कैश-फ्रेंडली नहीं है।

इस संस्करण के लिए बेंचमार्क बनाम फेसबुक पर मेरे पीआर पर अलेक्जेंड्रेस्कू के संस्करण बनाम मूर्खतापूर्ण

पर काम करता है unsigned, नहीं signed

inline uint32_t digits10(uint64_t v) {
  return  1
        + (std::uint32_t)(v>=10)
        + (std::uint32_t)(v>=100)
        + (std::uint32_t)(v>=1000)
        + (std::uint32_t)(v>=10000)
        + (std::uint32_t)(v>=100000)
        + (std::uint32_t)(v>=1000000)
        + (std::uint32_t)(v>=10000000)
        + (std::uint32_t)(v>=100000000)
        + (std::uint32_t)(v>=1000000000)
        + (std::uint32_t)(v>=10000000000ull)
        + (std::uint32_t)(v>=100000000000ull)
        + (std::uint32_t)(v>=1000000000000ull)
        + (std::uint32_t)(v>=10000000000000ull)
        + (std::uint32_t)(v>=100000000000000ull)
        + (std::uint32_t)(v>=1000000000000000ull)
        + (std::uint32_t)(v>=10000000000000000ull)
        + (std::uint32_t)(v>=100000000000000000ull)
        + (std::uint32_t)(v>=1000000000000000000ull)
        + (std::uint32_t)(v>=10000000000000000000ull);
}

0

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

double check=0, exponent=1000;

while(check<=1)
{
    check=number/pow(10, exponent);
    exponent--;
}

exponent=exponent+2;
cout<<exponent<<endl;

इससे मेरा उत्तर समाप्त हो गया जो वर्तमान में 10 ^ 1000 अंकों से कम अंकों के साथ काम करता है (घातांक का मान बदलकर बदला जा सकता है)।

पीएस मुझे पता है कि यह उत्तर दस साल देर से है, लेकिन मैं यहां 2020 पर आया था, इसलिए अन्य लोग इसका उपयोग कर सकते हैं।


-1
template <typename type>
class number_of_decimal_digits {   
    const powers_and_max<type> mPowersAndMax;
public:
    number_of_decimal_digits(){
    }   
    inline size_t ndigits( type i) const {
        if(i<0){
             i += (i == std::numeric_limits<type>::min());
             i=-i;
        }
        const type* begin = &*mPowersAndMax.begin();
        const type* end = begin+mPowersAndMax.size();
        return 1 + std::lower_bound(begin,end,i) - begin;
    }
    inline size_t string_ndigits(const type& i) const {
        return (i<0) + ndigits(i);
    }
    inline size_t operator[](const type& i) const {
       return string_ndigits(i);
    }
};

जहां powers_and_maxहम इस तरह (10^n)-1के सभी के nलिए है

(10^n) < std::numeric_limits<type>::max()

और std::numeric_limits<type>::max()एक सरणी में:

template <typename type>
struct powers_and_max : protected std::vector<type>{
    typedef std::vector<type> super;
    using super::const_iterator;
    using super::size;
    type& operator[](size_t i)const{return super::operator[](i)};
    const_iterator begin()const {return super::begin();} 
    const_iterator end()const {return super::end();} 
    powers_and_max() {
       const int size = (int)(log10(double(std::numeric_limits<type>::max())));
       int j = 0;
       type i = 10;
       for( ; j<size ;++j){
           push_back(i-1);//9,99,999,9999 etc;
           i*=10;
       }
       ASSERT(back()<std::numeric_limits<type>::max());
       push_back(std::numeric_limits<type>::max());
   }
};

यहाँ एक सरल परीक्षण है:

number_of_decimal_digits<int>  ndd;
ASSERT(ndd[0]==1);
ASSERT(ndd[9]==1);
ASSERT(ndd[10]==2);
ASSERT(ndd[-10]==3);
ASSERT(ndd[-1]==2);
ASSERT(ndd[-9]==2);
ASSERT(ndd[1000000000]==10);
ASSERT(ndd[0x7fffffff]==10);
ASSERT(ndd[-1000000000]==11);
ASSERT(ndd[0x80000000]==11);

बेशक एक निर्धारित सेट के किसी भी अन्य कार्यान्वयन के लिए इस्तेमाल किया जा सकता है powers_and_maxऔर अगर वहाँ ज्ञान था कि वहाँ क्लस्टरिंग होगी, लेकिन कोई ज्ञान नहीं है कि क्लस्टर कहाँ हो सकता है शायद एक स्व समायोजन पेड़ कार्यान्वयन सबसे अच्छा हो सकता है


-1

प्रभावी तरीका

int num;
int count = 0;
while(num)
{
   num /= 10;
   ++count;
}

#include <iostream>

int main()
{
   int num;
   std::cin >> num;

   std::cout << "number of digits for " << num << ": ";

   int count = 0;
   while(num)
   {
      num /= 10;
      ++count;
   }

   std::cout << count << '\n';

   return 0;
}

-1

पसंदीदा समाधान का C ++ 11 अद्यतन:

#include <limits>
#include <type_traits>
        template <typename T>
        typename std::enable_if<std::numeric_limits<T>::is_integer, unsigned int>::type
        numberDigits(T value) {
            unsigned int digits = 0;
            if (value < 0) digits = 1;
            while (value) {
                value /= 10;
                ++digits;
            }
            return digits;
        }

डबल, एट के साथ टेम्पलेट तात्कालिकता को रोकता है। अल।


-1
int numberOfDigits(double number){
    if(number < 0){
        number*=-1;
    }
    int i=0;
        while(number > pow(10, i))
            i++;    
    cout << "This number has " << i << " digits" << endl;
    return i;
}

-2

यह ऐसा करने का मेरा तरीका है:

   int digitcount(int n)
    {
        int count = 1;
        int temp = n;
        while (true)
        {
            temp /= 10;
            if (temp != 0) ++count;
            if (temp == 0) break;
        }

        return count;
    }

2
जबकि सच / ब्रेक सिंड्रोम: D
Петър Петров

-1 यह वही दृष्टिकोण है जिसका पहला उत्तर छह साल पहले दिया गया था, और यह कुछ नहीं जोड़ता है (वास्तव में यह काफी खराब है)।

-4

यहाँ एक अलग दृष्टिकोण है:

digits = sprintf(numArr, "%d", num);    // where numArr is a char array
if (num < 0)
    digits--;

यह कुशल नहीं हो सकता है, बस दूसरों ने जो सुझाव दिया है उससे कुछ अलग।


4
निवेदन अत्यंत कुशल के लिए था। यह विपरीत है।
इरा बैक्सटर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.