একটি পূর্ণসংখ্যার অঙ্কের সংখ্যা নির্ধারণের কার্যকর উপায়


144

সি ++ তে পূর্ণসংখ্যায় কতগুলি সংখ্যা রয়েছে তা নির্ধারণের খুব কার্যকর উপায় কী ?


11
কোন বেসে? 2? 10?
জ্যাকব কুলরে

2
আমি এটি বেস 10
শেঠ

1
আমি একবার সম্পর্কিত প্রশ্ন জিজ্ঞাসা করেছি: আপনি কোন সংখ্যায় প্রথম অঙ্কটি পেতে পারেন? নীচের মতো একই পদ্ধতিগুলির অনেকগুলি লোকের উত্তরে ব্যবহৃত হয়েছিল। এটি আপনার কাজের সাথে সম্পর্কিত হলে লিঙ্কটি এখানে রয়েছে [ stackoverflow.com/questions/701322/]
দিনাহ

ইনলাইন সমাবেশ যোগ্যতা অর্জন করে?
গিরিগিরিস আন্দ্রেসেক

1
যদিও এই সমস্ত উত্তরগুলি বেস 10 এর শর্তে রয়েছে, কোনও পছন্দসই বেসের জন্য ফলাফল গণনা করা খুব সহজ easy
ইরা

উত্তর:


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 বিট পূর্ণসংখ্যায় প্রসারিত হয় তখন কী ঘটে। আপনাকে ফিরে আসতে হবে এবং এই কোডটি সংশোধন করতে হবে remember বাস্তব জীবনে যা ঘটবে না এবং এটি সম্ভবত সঠিক আকারের একটি বাফার তৈরি করতে ব্যবহৃত হতে চলেছে আপনি এখন বড় আর্কিটেকচারগুলিতে রান সমস্যার কারণে নিজেকে সব ধরণের বাফারে খুলছেন।
মার্টিন ইয়র্ক

3
সংখ্যার অভিন্ন বন্টন ধরে নিলে, বিপরীত রৈখিক অনুসন্ধান (সর্বাধিক অঙ্ক থেকে শুরু করে 1 পর্যন্ত) বাইনারি অনুসন্ধানের তুলনায় গড়ে দ্রুত হতে পারে কারণ এন -1 সংখ্যার গ্রাফিকস.স্তানফোর্ড.ইডু/
এফএ।

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>। এখানে পোস্ট করা অন্যগুলির তুলনায় এটি দ্রুততর কিনা তা দেখতে আপনার প্রোফাইল দরকার profile ভাসমান পয়েন্ট যথার্থতার সাথে এটি কতটা দৃ is় তা আমি নিশ্চিত নই। এছাড়াও, যুক্তিটি নেতিবাচক মান হিসাবে স্বাক্ষরযুক্ত এবং লগটি সত্যই মিশে যায় না।


7
32 বিট ইনট এবং 56 বিট ভাসমানগুলির জন্য, এটি সম্ভবত কাজ করে। যদি ইনপুটটি দীর্ঘ হয় (b৪ বিট), ডাবল-স্পষ্টতা লগের 56 বিট এটি 10 ​​^ n এর বড় মানের নিকটে মানগুলির ক্ষেত্রে ভুল উত্তর তৈরি করতে পারে। 2 ^ 50 এর উপরে সমস্যা আশা করুন।
ইরা

1
লগ ফাংশনগুলি কতটা সঠিক তা নিয়েও প্রশ্ন রয়েছে। তারা আধুনিক লাইব্রেরিতে কতটা সঠিক তা আমি পরীক্ষা করে দেখিনি, এবং তাদের বিলিয়নের এক অংশের পক্ষে ভাল হতে অন্ধভাবে বিশ্বাস করা স্বাচ্ছন্দ্য বোধ করবে না।
ডেভিড থর্নলি

@ ডেভিডথর্নলি: সংকলক কমান্ড লাইনে নির্দিষ্ট না করা হলে লগ বা অন্যান্য গণিতের ক্রিয়াগুলি পুরোপুরি সুনির্দিষ্ট। কিছু সংকলন সময়ে x86 অন্তর্নিবেশে রূপান্তরিত হবে। কিছু বিদ্যমান নেই এবং বিদ্যমান অভ্যন্তরের সূত্রে প্রসারিত হবে। উদাহরণস্বরূপ আপনি যদি ব্যবহার করছেন -fpfastআপনি x87 এর পরিবর্তে এসএসই ইনস্ট্রিনসিকের ব্যবহার দেখতে পেলেন যা নির্ভুলতা আইআরসি-তে কম গ্যারান্টি দেয়। কিন্তু ডিফল্টরূপে কোনও সমস্যা নেই।
v.oddou

@ ডেভিডথর্নলি: এটি নির্ভুলতার চেয়ে বেশি। প্রশ্নটি প্রাসঙ্গিক কে এর জন্য লগ 10 (10 ^ কে) ≥ কে গ্যারান্টিযুক্ত কিনা তা নয় for এটাই নিশ্চিত যে কোনও অনিবার্য বৃত্তাকার ত্রুটি সঠিক পথে চলে। k + eps ফলস্বরূপ কাজ করে, k - eps দেয় না। এবং "পুরোপুরি নির্ভুল" নির্বোধ।
gnasher729

1
আই> 0 পরীক্ষাটি আই> 9
প্যাট

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
এবং আমি এই সমাধানটি দ্রুততম হতে পারলে অবাক হব না।
ভিজিওন

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 এর জন্য কাজ করে না Second দ্বিতীয়ত আপনার সমাধানটি ভেরিয়েবলের সাধারণ ক্ষেত্রে অনুপযুক্ত। তৃতীয়ত, আপনি যদি ধ্রুবক আক্ষরিক ব্যবহার করে থাকেন তবে এটি ইতিমধ্যে জানেন যে এর কতগুলি সংখ্যা রয়েছে।
ভিটালী

এটি 0 এর জন্যও কাজ করে। এটি যে কোনও বেসের জন্যও কাজ করে। বাকিগুলি বৈধ পয়েন্ট যা আমি ইতিমধ্যে উল্লেখ করেছি।
blinnov.com

3
আমি আসলে মনে করি না। এটি ব্যর্থ হয় 0এবং বেসেও ব্যর্থ হয় 1:) এবং যদি বেস হিসাবে দেওয়া হয় তবে শূন্য ত্রুটি দ্বারা বিভাজন দেয় 0। যদিও এটি স্থির করা যায়। যাইহোক আমি একটি খুব পুরানো পোস্টে নিটপিক করছি, তাই দুঃখিত, এটি ঠিক যে আমি মনে করি এটি রসিকতা হওয়ার দরকার নেই এবং এটি আসলে কার্যকর হতে পারে।
tjm

9

আপনি যে উত্তরটি স্বীকার করেছেন তার আরও সংক্ষিপ্ত সংস্করণের জন্য বিট টুইডলিং হ্যাকগুলি দেখুন । প্রথমে বড় কনস্ট্যান্টগুলি পরীক্ষা করে যদি আপনার ইনপুটটি সাধারণত বিতরণ করা হয় তবে তাড়াতাড়ি উত্তর খুঁজে পাওয়ারও সুবিধা রয়েছে। (v >= 1000000000)মানগুলির% cat% ক্যাচ করে, সুতরাং প্রথমে এটি পরীক্ষা করে গড়ে গড়ে দ্রুততর হয়।


বিট-টুইডলিং আসলে দ্রুত হয় কিনা তা অস্পষ্ট। এমনকি সবচেয়ে খারাপ ক্ষেত্রেও, আমার পরিবর্তিত পদ্ধতির জন্য 4 টি তুলনা প্রয়োজন (আমি আরও বিভাজন পরীক্ষা করে দেখলে এটি 3 এ নামিয়ে নিতে সক্ষম হতে পারে, যদিও এটি অসম্ভব বলে মনে হচ্ছে)। আমি গুরুতরভাবে সন্দেহ করি যে এটি গাণিতিক ক্রিয়াকলাপগুলি + মেমরি লোডগুলি দ্বারা পরাজিত হতে চলেছে (যদিও এটি যথেষ্ট পরিমাণে অ্যাক্সেস করা হলেও সেগুলি সিপিইউ ক্যাশে অদৃশ্য হয়ে যায়)। মনে রাখবেন, তারা যে উদাহরণ দেয়, লগ বেস 2টিকে তারা কিছু বিমূর্ত IntegerLogBase2 ফাংশন হিসাবে লুকিয়ে রাখে (যা নিজেই সস্তা নয়)।
ভিটালী

ঠিক যেমন অনুসরণ করা হয়, হ্যাঁ যদি সংখ্যাগুলি সাধারণত বিতরণ করা হয় তবে ইন-অর্ডার চেক করা আরও দ্রুত। তবে, এটি সবচেয়ে খারাপ ক্ষেত্রে দ্বিগুণ ধীর হয়ে যাওয়ার অধঃপতনের ক্ষেত্রে রয়েছে। ইনপুট স্পেসের পরিবর্তে অঙ্কের সংখ্যা দ্বারা বিভাজনিত পদ্ধতির মানে হল যে আচরণটির অধঃপতন ঘটে না এবং সর্বদা অনুকূলভাবে সম্পাদন করে। তদতিরিক্ত, মনে রাখবেন যে আপনি এই ধারণাটি তৈরি করছেন যে সংখ্যাগুলি সমানভাবে বিতরণ করা হবে। বস্তুত, তারা আরো কিছু <a href=" en.wikipedia.org/wiki/... এর সাথে সম্পর্কিত বন্টন অনুসরণ করার সম্ভাবনা বেশি> আমার অনুমান করা হবে।
Vitali

বিট টুইডলিং হ্যাকগুলি উপরের পার্টিশন পদ্ধতির চেয়ে দ্রুত নয়, তবে আপনার যদি এখানে ভাসমানের মতো আরও সাধারণ কেস থাকে তবে এগুলি সম্ভবত আকর্ষণীয়।
করউইন জয়

1
বিট টুইডলিং হ্যাকগুলি ইন লগ 2 প্রদান করে int লগ 10 পাওয়ার একটি উপায় প্রস্তাব করে। এটি বেশিরভাগ তুলনা / শাখাগুলিকে অন্তর্ভুক্ত করে ইনট লগ 2 পাওয়ার বিভিন্ন উপায়ের পরামর্শ দেয়। (আমি মনে করি আপনি অপ্রত্যাশিত শাখার দামকে কম মূল্যায়ন করছেন, ভিটালী)। আপনি যদি ইনলাইন x86 এএসএম ব্যবহার করতে পারেন তবে বিএসআর নির্দেশিকা আপনাকে একটি মানের ইনট লগ 2 দেবে (অর্থাত্ সর্বাধিক উল্লেখযোগ্য সেট বিটের বিট সূচক)। এটি কে 8 (10 চক্র ল্যাটেন্সি) এর দিকে কিছুটা ধীরে ধীরে, তবে কোর 2 (2 বা 3 চক্রের বিলম্ব) এ দ্রুত। এমনকি কে 8 এ, তুলনার তুলনায় ভাল হতে পারে।
পিটার কর্ডস

কে 10-তে, এলজ্যাক্ট শীর্ষস্থানীয় জিরো গণনা করে, তাই এটি প্রায় বিএসআর এর সমান, তবে 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
যদিও এটি এলওসি-র ক্ষেত্রে কার্যকর, লগের স্বীকৃত উত্তর ব্যবহারে উল্লিখিত হিসাবে সম্ভবত সেরা সম্পাদনা দেবে না give
আয়ান

@ ইয়ান কেন না? এটি কেবল দু'টি এফপিইউ নির্দেশনা। সমস্ত শাখার চেয়ে মাইল ভাল এবং অন্যান্য উত্তরে লুপ।
লার্নের মারকুইস

5

আগের পোস্টারটি একটি লুপকে 10 দ্বারা বিভক্ত করার পরামর্শ দিয়েছিল যেহেতু আধুনিক মেশিনগুলিতে বহুগুণ অনেক বেশি দ্রুত, আমি পরিবর্তে নিম্নলিখিত কোডটি সুপারিশ করব:

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

1
শয়তান এই বিবরণে রয়েছে - std :: numeric_limits <int> :: সর্বাধিক == সংখ্যা বলার সাথে কী ঘটে - এটি শেষ হতে সমস্যা হতে পারে
pgast

2
আপনি যদি এই ক্ষেত্রেটি সম্পর্কে উদ্বিগ্ন হন তবে আপনি খুব বড় মানগুলি পরিচালনা করতে একটি অতিরিক্ত আইএফ যুক্ত করতে পারেন।
ইরা

2
আমার পর্যবেক্ষণ করা উচিত যে x86 মেশিনে, এই ক্ষেত্রে ব্যবহৃত ধ্রুবক 10 দ্বারা গুণ করা আসলে এলইএ আর 2, [8 * আর 1 + আর 1], অ্যাডিডি আর 1, আর 2 হিসাবে সংকলক দ্বারা বাস্তবায়িত হতে পারে তাই এটি সর্বোচ্চ 2 ঘড়ি লাগে। ভেরিয়েবলগুলি দ্বারা গুণিত করা দশগুলি ঘড়ি নেয়, এবং ভাগগুলি আরও খারাপ হয়।
ইরা

বিভাজনের পদ্ধতির সাথে সুবিধা হ'ল আপনাকে নেতিবাচক সংখ্যা সম্পর্কে চিন্তা করতে হবে না।
জোহানেস স্কাউব - লিটব

1
আমি বিভাগের পদ্ধতির বিপরীতে বহুগুণ পদ্ধতির (সাইন ইস্যুটি সরিয়ে দেওয়ার জন্য একটি কল্প দিয়ে) বেঞ্চমার্ক করেছি। আমার মেশিনে বিভাগের পদ্ধতিটি গুণকের পদ্ধতির চেয়ে 2 গতি কম। এটি অকাল অপটিমাইজেশন হোক বা না আসলে এটি কোথায় এবং কীভাবে ডাকা হবে তার উপর নির্ভর করে।
স্পেসমুজ

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))

এটি প্ল্যাটফর্ম নির্দিষ্ট এবং সামান্য ভুল, তবে কোনও শাখা, বিভাগ বা ভাসমান পয়েন্টে রূপান্তর জড়িত না। আপনার প্রয়োজনের উপর সব নির্ভর করে।

আমি কেবল পিপিসি নির্দেশাবলী হাতছাড়া জানি, তবে অন্যান্য আর্কিটেকচারেও একই নির্দেশ থাকতে হবে।


এই সমাধানটি লগ 2 (15) = 4 বিট এবং লগ 2 (9) = 4 বিটের গণনা করে। তবে 15 এবং 9 এর দশমিক অঙ্কের বিভিন্ন সংখ্যা মুদ্রণের জন্য প্রয়োজন। সুতরাং এটি কাজ করে না, যদি না আপনি কখনও কখনও অনেকগুলি সংখ্যা দিয়ে নিজের সংখ্যা মুদ্রণ করতে আপত্তি করেন mind তবে সেক্ষেত্রে আপনি উত্তরের জন্য সর্বদা "10" বেছে নিতে পারেন।
ইরা

বাহ, একটি আনুমানিক ফাংশন। খুশী হলাম।
doug65536

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;
}

লুপটির বাইরে অতিরিক্ত পরীক্ষা উত্তোলনের মাধ্যমে উন্নত পারফরম্যান্সটি পেতে আপনার প্ল্যাটফর্মের প্রতিটি ধরণের স্থির প্রত্যাবর্তনের জন্য আপনাকে সর্বোচ্চ_ডেসিমাল () বিশেষজ্ঞ করতে হবে। পর্যাপ্ত পরিমাণে যাদু সংকলক কলটিকে একটি ধ্রুবককে সর্বোচ্চ_ ডেসিমাল () এ অনুকূলিত করতে পারে, তবে বেশিরভাগ সংকলকগুলির সাথে আজ বিশেষত্ব আরও ভাল। যেমনটি দাঁড়িয়েছে, এই সংস্করণটি সম্ভবত ধীরে ধীরে কারণ লুপ থেকে সরিয়ে নেওয়া পরীক্ষাগুলির চেয়ে ম্যাক্স_ডেসিমেলের বেশি খরচ হয়।

আমি পাঠকের জন্য অনুশীলন হিসাবে সব ছেড়ে দেব।


আপনি উপরের সীমাটি প্রথমে পৃথক শর্তসাপেক্ষে পরীক্ষিত করতে চান যাতে আপনি এটি প্রতিটি লুপ পুনরাবৃত্তিতে পরীক্ষা করে না।
ইরা

আপনি এই টেম্প টিতে 10 লাগাতে চান না। সংকলকটি টি দ্বারা গুণকে একটি বাস্তব পরিবর্তনশীল দ্বারা গুণিত করতে বিবেচনা করতে পারে এবং একটি সাধারণ উদ্দেশ্যে গুণিত নির্দেশ ব্যবহার করে। আপনি যদি পরিবর্তে "ফলাফল * = 10" লিখেছিলেন; সংকলক অবশ্যই ধ্রুবক 10 দ্বারা গুণটি লক্ষ্য করবে এবং কয়েকটি শিফট এবং সংযোজন সহ এটি প্রয়োগ করবে যা অত্যন্ত দ্রুত।
ইরা

যদি টি দ্বারা গুণনটি সর্বদা 10 দ্বারা গুণ হয় তবে হ্যাঁ, সংকলক শক্তি হ্রাস করতে পারে। যাইহোক, টি এই ক্ষেত্রে লুপ-আক্রমণকারী নয় (এটি আমার কাছে পড়ে থাকা একটি পূর্ণসংখ্যা শক্তি ফাংশনের কেবলমাত্র একটি পরিবর্তন)। সঠিক অপ্টিমাইজেশন হ'ল ধ্রুবক ফেরত টাইপের বিশেষীকরণ। যাইহোক, আপনি ঠিক বলেছেন যে, এই ক্ষেত্রে, ফাংশনটি সর্বদা একটি শক্তিতে 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বর্তমানে লুপটিতে প্রক্রিয়া করা হয় এমন নম্বরের জন্য আপনাকে মান দেয়। উদাহরণস্বরূপ ১76 number76 সংখ্যাটির জন্য ডিজিটের মানটি:
4 র্থ লুপের 1 য় 3
য় লুপ
7-এ
1 lo লুপ 7 এ 6 lo


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) );

উপরে 'blinnov.com' থেকে 'ব্যবহারিক তামাশা "জন্য কারেকশন
Adolfo

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

পূর্ণসংখ্যা 'এক্স' এর জন্য আপনি অঙ্কগুলির সংখ্যা জানতে চান, কোনও লুপ ব্যবহার না করেই এই সমাধানটি এক লাইনে একটি সূত্রে কাজ করে তাই এটি এই সমস্যাটির মধ্যে দেখা সবচেয়ে উপযুক্ত সমাধান।

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

INT_MAX এবং negativeণাত্মক সংখ্যার জন্যও ব্যর্থ।
রানু

@ranu INT_MAX এর জন্য ব্যর্থ হয় কীভাবে? যুক্তিটি কখন রূপান্তরিত হয় 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

দ্রুত যদি আরও দক্ষ হয় তবে এটি আন্দ্রে আলেকজান্দ্রেস্কুর উন্নতি on । তাঁর সংস্করণটি ইতিমধ্যে নিষ্পাপ উপায়ের চেয়ে দ্রুত ছিল (প্রতিটি অঙ্কে 10 দ্বারা বিভাজক)। নীচের সংস্করণটি সব ধরণের জন্য কমপক্ষে x86-64 এবং এআরএম এ ধ্রুবক সময় এবং দ্রুত, তবে দ্বিগুণ বাইনারি কোড দখল করে, তাই এটি ক্যাশে-বান্ধব নয়।

ফেসবুক বোকামিটিতে আমার পিআর-এ এই সংস্করণ বনাম অ্যালেক্সান্দ্রেস্কুর সংস্করণটির জন্য বেঞ্চমার্কগুলি

কাজ করে 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 এরও কম সংখ্যার (সংখ্যাযুক্তের মান পরিবর্তন করে পরিবর্তন করা যেতে পারে) সংখ্যার সাথে কাজ করে।

PS আমি জানি এই উত্তরটি দশ বছর দেরিতে তবে আমি এখানে ২০২০ এ এসেছি যাতে অন্য লোকেরা এটি ব্যবহার করতে পারে।


-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এবং যদি সেখানে জ্ঞান ছিল যে সেখানে ক্লাস্টারিং হবে তবে ক্লাস্টারটি সম্ভবত কোনও স্ব সামঞ্জস্যকারী গাছের বাস্তবায়ন হতে পারে সে সম্পর্কে কোনও জ্ঞান নেই best


-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

পছন্দসই সমাধানটির সি ++ 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
সত্য / বিরতি সিন্ড্রোম থাকাকালীন: ডি
Петров

-1 এটি একই পদ্ধতির যা প্রথম উত্তরটি ছয় বছর আগে দিয়েছে এবং এতে কিছুই যুক্ত হয় না (বাস্তবে এটি উল্লেখযোগ্যভাবে খারাপ) is

-4

এখানে একটি পৃথক পদ্ধতির:

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

এটি দক্ষ নাও হতে পারে, অন্যরা যা বলেছিল তার চেয়ে আলাদা কিছু।


4
অনুরোধটি ছিল অত্যন্ত দক্ষতার জন্য। এটি বিপরীত।
ইরা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.