কোনও সংখ্যা 2 এর পাওয়ার কিনা তা কীভাবে চেক করবেন


583

একটি সংখ্যা 2 এর শক্তি কিনা তা পরীক্ষা করার জন্য আজ আমার একটি সাধারণ অ্যালগরিদম প্রয়োজন।

অ্যালগরিদমটি হওয়া দরকার:

  1. সহজ
  2. যে কোনও ulongমানের জন্য সঠিক ।

আমি এই সাধারণ অ্যালগরিদম নিয়ে এসেছি:

private bool IsPowerOfTwo(ulong number)
{
    if (number == 0)
        return false;

    for (ulong power = 1; power > 0; power = power << 1)
    {
        // This for loop used shifting for powers of 2, meaning
        // that the value will become 0 after the last shift
        // (from binary 1000...0000 to 0000...0000) then, the 'for'
        // loop will break out.

        if (power == number)
            return true;
        if (power > number)
            return false;
    }
    return false;
}

তবে আমি ভেবেছিলাম, কীভাবে চেক করা ঠিক একটি গোলাকার নম্বর কিনা ? তবে আমি যখন 2 ^ 63 + 1 পরীক্ষা করেছিলাম তখন রাউন্ডিংয়ের কারণে ঠিক 63 ফিরে আসল। সুতরাং আমি 2 টি পাওয়ার 63 টি মূল সংখ্যার সমান কিনা তা পরীক্ষা করে দেখেছি - এবং এটি হ'ল কারণ গণনাটি এসে করা হয় এবং সঠিক সংখ্যায় নয়:log2 xMath.Logdouble

private bool IsPowerOfTwo_2(ulong number)
{
    double log = Math.Log(number, 2);
    double pow = Math.Pow(2, Math.Round(log));
    return pow == number;
}

এই ফিরে trueদেওয়া ভুল মান: 9223372036854775809

আরও ভাল অ্যালগরিদম আছে?


1
আমি মনে করি সমাধান দুটি ভুজের সমষ্টি হিসাবে যেমন (x & (x - 1))মিথ্যা ধনাত্মকতা ফিরে আসতে পারে । X8 + 16
জো ব্রাউন

32
সমস্ত সংখ্যা দুটি হিসাবে একটি শক্তির যোগফল হিসাবে রচনা করা যেতে পারে, আমরা বাইনারি কোনও সংখ্যা প্রতিনিধিত্ব করতে পারেন কেন। তদ্ব্যতীত, আপনার উদাহরণ একটি মিথ্যা ইতিবাচক প্রত্যাবর্তন করবে না, কারণ 11000 & 10111 = 10000! = 0.
ভিএলএসডি

1
@ জোব্রাউন এটির কোনও মিথ্যা ইতিবাচকতা নেই। প্রকৃতপক্ষে প্রকাশ দুটি দুটি শক্তির যোগফলের বৃহত্তর প্রদান করে।
স্যামি বেঞ্চিরিফ

উত্তর:


1217

এই সমস্যার জন্য একটি সহজ কৌশল আছে:

bool IsPowerOfTwo(ulong x)
{
    return (x & (x - 1)) == 0;
}

দ্রষ্টব্য, এই ফাংশনটি এর trueজন্য প্রতিবেদন করবে 0, যা কোনও পাওয়ার নয় 2। আপনি যদি এটি বাদ দিতে চান তবে এখানে কীভাবে:

bool IsPowerOfTwo(ulong x)
{
    return (x != 0) && ((x & (x - 1)) == 0);
}

ব্যাখ্যা

এমএসডিএন সংজ্ঞা থেকে প্রথম এবং সর্বাগ্রে বিটওয়াইস বাইনারি এবং অপারেটর:

বাইনারি এবং অপারেটরগুলি ইন্টিগ্রাল টাইপ এবং বুলের জন্য পূর্বনির্ধারিত। অবিচ্ছেদ্য প্রকারের জন্য, & এর অপারেশনগুলির লজিকাল বিটওয়াইস এবং গণনা করে। বুল অপারেন্ডসগুলির জন্য, & এর অপারেশনগুলির লজিকাল এবং গণনা করে; এটি হ'ল, ফলাফলটি যদি সত্য হয় তবেই যদি এর দুটি অপারেশন সত্য হয়।

এখন আসুন একবার দেখে নেওয়া যাক কীভাবে এটি সমস্ত কার্যকর হয়:

ফাংশনটি বুলিয়ান দেয় (সত্য / মিথ্যা) এবং স্বাক্ষরবিহীন দীর্ঘ (এই ক্ষেত্রে, এক্স) প্রকারের একটি আগত প্যারামিটার গ্রহণ করে। আসুন আমরা সরলতার জন্য ধরে নিই যে কেউ 4 মানটি পাস করেছে এবং ফাংশনটিকে এভাবে বলেছে:

bool b = IsPowerOfTwo(4)

এখন আমরা এক্স এর প্রতিটি উপস্থিতি 4 দিয়ে প্রতিস্থাপন করব:

return (4 != 0) && ((4 & (4-1)) == 0);

ওয়েল আমরা ইতিমধ্যে জানি যে 4! = 0 সত্য থেকে প্রমাণিত হয়, এতদূর এত ভাল। কিন্তু কি ব্যাপারে:

((4 & (4-1)) == 0)

এটি অবশ্যই এটিতে অনুবাদ করে:

((4 & 3) == 0)

তবে ঠিক কী 4&3?

4 এর বাইনারি উপস্থাপনা 100 এবং 3 এর বাইনারি উপস্থাপনা 011 (মনে রাখবেন এবং এই সংখ্যাগুলির বাইনারি উপস্থাপনা গ্রহণ করুন)। তাহলে আমাদের আছে:

100 = 4
011 = 3

এই মানগুলি প্রাথমিক সংযোজনের মতো অনেকগুলি সজ্জিত করার কথা ভাবুন। &অপারেটর বলছেন যে তারপর 1 টি ফলাফল হলে যদি দুটি মানই 1 এর সমান হয়, অন্যথায় এটি 0. সুতরাং হয় 1 & 1 = 1, 1 & 0 = 0, 0 & 0 = 0, এবং 0 & 1 = 0। সুতরাং আমরা গণিত:

100
011
----
000

ফলাফলটি সাধারণভাবে ০. সুতরাং আমরা ফিরে যাই এবং আমাদের রিটার্নের বিবৃতিটি এখন কী অনুবাদ করে তা দেখুন:

return (4 != 0) && ((4 & 3) == 0);

যা এখন অনুবাদ করে:

return true && (0 == 0);
return true && true;

আমরা সকলেই জানি যে true && trueএটি কেবলমাত্র trueএবং এটি আমাদের উদাহরণস্বরূপ 4 টি 2 এর শক্তি।


56
@ ক্রিপ: সংখ্যাটি বাইনারি ফর্ম 1000 ... 000 এর হবে। আপনি এটি -1 করলে এটি 0111 ... 111 ফর্মের হবে। সুতরাং, দুই নম্বর এর বাইনারি এবং স্থাপিত হবে 000000. এই অ শক্তি অফ দুই দুই, 1010100 যেহেতু উদাহরণস্বরূপ 1010011 হয়ে, একটি (অব্যাহত ...) ফলে জন্য ঘটবে না হবে
Configurator

47
... বাইনারি পরে এবং 1010000 এ ফলাফল। একমাত্র মিথ্যা ধনাত্মক 0 হবে, তাই আমি ব্যবহার করব: রিটার্ন (x! = 0) && ((x & (x - 1)) == 0);
Configurator

6
ক্রিপ্প, বিবেচনা করুন (2: 1, 10: 1) (4: 3, 100: 11) (8: 7, 1000: 111) (16:15, 10000: 1111) প্যাটার্নটি দেখুন?
থমাস এল হোলাডে

13
@ শুগিকুক: দুটির পরিপূরক হ'ল নেতিবাচক সংখ্যাগুলি কীভাবে প্রতিনিধিত্ব করা হয়। যেহেতু এটি একটি স্বাক্ষরযুক্ত স্বাক্ষর পূর্ণসংখ্যা তাই নেতিবাচক সংখ্যার প্রতিনিধিত্ব প্রাসঙ্গিক নয়। এই কৌশলটি কেবল ননজেগিটিভ পূর্ণসংখ্যার বাইনারি উপস্থাপনার উপর নির্ভর করে।
গ্রেগ হিউগিল

4
@ সোপবক্স - আরও সাধারণ কী? শূন্য বা অ-শূন্য সংখ্যা যা দুটি নয়? এটি এমন একটি প্রশ্ন যা আপনি আরও কিছু প্রসঙ্গ ছাড়া উত্তর দিতে পারবেন না। এবং এটি সত্যই, সত্যিই যাই হোক না কেন কিছু যায় আসে না।
কনফিগারকারী

97

কিছু সাইট যা এই এবং অন্যান্য বিট টুইডলিং হ্যাকগুলি নথি করে ব্যাখ্যা করে:

এবং তাদের গ্র্যান্ডাডি , জুনিয়র হেনরি ওয়ারেনের "হ্যাকারস ডিলাইট" বইটি লিখেছেন :

শান অ্যান্ডারসনের পৃষ্ঠাটি যেমন ব্যাখ্যা করেছে, এক্সপ্রেশনটি ((x & (x - 1)) == 0)ভুলভাবে নির্দেশ করে যে 0 0 এর একটি শক্তি He তিনি ব্যবহার করার পরামর্শ দেন:

(!(x & (x - 1)) && x)

যে সমস্যাটি সংশোধন করতে।


4
0 2 এর একটি শক্তি ... 2 ^ -inf = 0.;);););
মাইকেল ব্রে

4
যেহেতু এটি একটি সি # ট্যাগড থ্রেড, এটি উল্লেখ করার মতো যে শেষ অভিব্যক্তিটি (শান অ্যান্ডারসনের) সি # তে অবৈধ, যেহেতু !কেবল বুলিয়ান ধরণের ক্ষেত্রেই প্রয়োগ করা যেতে পারে, এবং &&উভয় অপারেশন বুলিয়ানও প্রয়োজন - (ব্যবহারকারী সংজ্ঞায়িত অপারেটর ব্যতীত অন্যান্য জিনিসগুলি সম্ভব করে ulong
তুলুন

40

return (i & -i) == i


2
কোনও ইঙ্গিত কেন এটি করবে বা কাজ করবে না? আমি কেবল জাভাতে তার নির্ভুলতা পরীক্ষা করেছি, যেখানে কেবলমাত্র স্বাক্ষরিত ইনস / লং রয়েছে। যদি এটি সঠিক হয় তবে এটি সর্বোত্তম উত্তর হবে। দ্রুত + ছোট
এন্ড্রেয়াস পিটারসন

7
এটি দুটি এর পরিপূরক স্বরলিপিটির একটি বৈশিষ্ট্যের সুবিধা গ্রহণ করে: আপনি যে কোনও সংখ্যার নেতিবাচক মান গণনা করতে খানিকটা নেতিবাচক ব্যবহার করেন এবং ফলাফলটিতে 1 যুক্ত করেন। অন্তত গুরুত্বপূর্ণ বিট iযা সেট এছাড়াও সেট করা হবে -i। নীচের বিটগুলি 0 হবে (উভয় মানের ক্ষেত্রে) যখন এর উপরে বিটগুলি একে অপরের প্রতি সম্মানের সাথে উল্টানো হবে। i & -iসুতরাং এর মান iহ'ল সর্বনিম্ন তাৎপর্যপূর্ণ সেট বিট (যা দুইটির একটি শক্তি)। যদি iএকই মান থাকে তবে এটি ছিল একমাত্র বিট সেট। iএকই কারণে যে 0 হয় তখন এটি ব্যর্থ i & (i - 1) == 0হয়।
মাইকেল কারম্যান

6
যদি iস্বাক্ষরবিহীন প্রকারের হয় তবে এর সাথে দ্বিগুণ পরিপূরকের কোনও সম্পর্ক নেই। আপনি কেবলমাত্র মডিউলার গাণিতিক এবং বিটওয়াইস এবং এর বৈশিষ্ট্যগুলি ব্যবহার করছেন।
আর .. গিটহাব বন্ধ করুন ICE

2
এটি i==0( যদি রিটার্ন (0&0==0)হয় true) কার্যকর হয় না। এটি হওয়া উচিতreturn i && ( (i&-i)==i )
bobobobo

22
bool IsPowerOfTwo(ulong x)
{
    return x > 0 && (x & (x - 1)) == 0;
}

3
এই সমাধান (দীর্ঘ যদি পরিবর্তে ulong এর) কারণ এটি ঋণাত্মক সংখ্যা সাথে মোকাবিলা করতে পারেন নেতিবাচক মধ্যে পাস করতে সক্ষম হয়েছি উত্তম।
স্টিভেন

এক দশমিক কেন এই ক্ষেত্রে দুটি হিসাবে শক্তি হয়?
ক্রিস ফ্রিসিনা

21

আমি সম্প্রতি এই সম্পর্কে একটি নিবন্ধ লিখেছিলাম http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/ এ । এতে বিট কাউন্টিং, লোগারিদমগুলি কীভাবে সঠিকভাবে ব্যবহার করতে হবে, ক্লাসিক "এক্স অ্যান্ড অ্যান্ড! (এক্স এবং (এক্স - 1))" চেক এবং অন্যান্যকে অন্তর্ভুক্ত করা হয়েছে।


17

এখানে একটি সাধারণ সি ++ সমাধান:

bool IsPowerOfTwo( unsigned int i )
{
    return std::bitset<32>(i).count() == 1;
}

8
জিসিসি-তে এটি একক জিসিসি বিল্টিন নামক সংকলন করে __builtin_popcount। দুর্ভাগ্যক্রমে, প্রসেসরের একটি পরিবারের এখনও এটি করার জন্য একক সমাবেশের নির্দেশ নেই (x86), সুতরাং পরিবর্তে এটি বিট গণনার দ্রুততম পদ্ধতি। অন্য যে কোনও স্থাপত্যে এটি একক সমাবেশ নির্দেশ assembly
deft_code

3
@ ডিফ্ট_কোড আরও নতুন x86 মাইক্রোর্কিটেকচার সমর্থনpopcnt
ফুকলভ

13

গৃহীত উত্তরের নিম্নলিখিত সংযোজন কিছু লোকের পক্ষে কার্যকর হতে পারে:

দু'জনের একটি শক্তি, যখন বাইনারিতে প্রকাশ করা হয়, সর্বদা 1 টির পরে এন জিরো যেখানে n এর চেয়ে বড় বা সমান হয় এর মত দেখাবে Ex প্রাক্তন:

Decimal  Binary
1        1     (1 followed by 0 zero)
2        10    (1 followed by 1 zero)
4        100   (1 followed by 2 zeroes)
8        1000  (1 followed by 3 zeroes)
.        .
.        .
.        .

ইত্যাদি।

আমরা যখন 1এই ধরণের সংখ্যা থেকে বিয়োগ করি তখন সেগুলি 0 এর পরে n হয় এবং আবার n উপরে থাকে। উদা:

Decimal    Binary
1 - 1 = 0  0    (0 followed by 0 one)
2 - 1 = 1  01   (0 followed by 1 one)
4 - 1 = 3  011  (0 followed by 2 ones)
8 - 1 = 7  0111 (0 followed by 3 ones)
.          .
.          .
.          .

ইত্যাদি।

আসছেন ক্রুসে

যখন আমরা কিছু সংখ্যক এবং একটি সংখ্যার x, যা 2 এর শক্তি, এবং x - 1কী করব?

এর একটি xশূন্যের সাথে একত্রিত হয়ে যায় x - 1এবং সমস্ত শূন্যগুলি এর xসাথে একত্রিত হয় x - 1, যার ফলে বিটওয়াইজ হয় এবং ফলাফল হয় ০. এবং এটিই আমাদের উপরে উল্লিখিত একক লাইনের উত্তরটি সঠিক বলে উল্লেখ করেছে।


উপরে গৃহীত উত্তরের সৌন্দর্যে আরও যুক্ত -

সুতরাং, আমাদের এখন আমাদের হাতে সম্পত্তি আছে:

যখন আমরা যে কোনও সংখ্যা থেকে 1 বিয়োগ করি, তখন বাইনারি উপস্থাপনায় ডানদিকের 1 টি 0 হয়ে যায় এবং সেই ডানদিকের 1 এর আগে সমস্ত শূন্য এখন 1 হবে

এই সম্পত্তিটির এক দুর্দান্ত ব্যবহার সন্ধানে - প্রদত্ত সংখ্যার বাইনারি উপস্থাপনায় কয়টি 1 টি উপস্থিত? প্রদত্ত পূর্ণসংখ্যার জন্য এটি করার জন্য সংক্ষিপ্ত এবং মিষ্টি কোডটি xহ'ল:

byte count = 0;
for ( ; x != 0; x &= (x - 1)) count++;
Console.Write("Total ones in the binary representation of x = {0}", count);

উপরে বর্ণিত ধারণাটি থেকে প্রমাণিত হওয়া সংখ্যার আরেকটি দিক হ'ল "কি প্রতিটি ধনাত্মক সংখ্যাকে 2 এর শক্তির যোগফল হিসাবে উপস্থাপন করা যায়?"

হ্যাঁ, প্রতিটি ধনাত্মক সংখ্যা 2 এর সমষ্টি হিসাবে উপস্থাপিত হতে পারে যে কোনও সংখ্যার জন্য, এর বাইনারি উপস্থাপনা নিন। প্রাক্তন: নাম্বার নিন 117

The binary representation of 117 is 1110101

Because  1110101 = 1000000 + 100000 + 10000 + 0000 + 100 + 00 + 1
we have  117     = 64      + 32     + 16    + 0    + 4   + 0  + 1

@ মিচি: আমি কোথাও দাবি করেছিলাম যে 0টি ইতিবাচক সংখ্যা? নাকি 2 এর শক্তি?
displayName

হ্যাঁ, উদাহরণ হিসাবে 0 স্থাপন করে এবং সেই গাণিতিকটিকে উপস্থাপনের ভিতরে গাণিত করে। এটি একটি বিভ্রান্তি তৈরি করে।
মিশি

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

10

প্রশ্ন পোস্ট করার পরে আমি নিম্নলিখিত সমাধানগুলি নিয়ে ভাবলাম:

বাইনারি অঙ্কগুলির ঠিক কোনওটি একটি কিনা তা আমাদের খতিয়ে দেখা উচিত। সুতরাং আমরা কেবল একবারে সংখ্যাটি এক অঙ্কে স্থানান্তরিত করি এবং trueএটি 1 সমান হলে ফিরে আসি any যদি কোনও বিন্দুতে আমরা একটি বিজোড় সংখ্যা ( (number & 1) == 1) দিয়ে আসি , আমরা জানি ফলাফল কি false। এটি প্রমাণিত হয়েছে (একটি বেঞ্চমার্ক ব্যবহার করে) প্রকৃত মানগুলির জন্য (বৃহত) মূল পদ্ধতির তুলনায় কিছুটা দ্রুত এবং মিথ্যা বা ছোট মানগুলির জন্য আরও দ্রুত।

private static bool IsPowerOfTwo(ulong number)
{
    while (number != 0)
    {
        if (number == 1)
            return true;

        if ((number & 1) == 1)
            // number is an odd number and not 1 - so it's not a power of two.
            return false;

        number = number >> 1;
    }
    return false;
}

অবশ্যই গ্রেগের সমাধানটি আরও ভাল।


10
    bool IsPowerOfTwo(int n)
    {
        if (n > 1)
        {
            while (n%2 == 0)
            {
                n >>= 1;
            }
        }
        return n == 1;
    }

এবং এখানে একটি সংখ্যা অন্য সংখ্যার শক্তি কিনা তা অনুসন্ধান করার জন্য একটি সাধারণ অ্যালগরিদম।

    bool IsPowerOf(int n,int b)
    {
        if (n > 1)
        {
            while (n % b == 0)
            {
                n /= b;
            }
        }
        return n == 1;
    }

6
bool isPow2 = ((x & ~(x-1))==x)? !!x : 0;

1
এটা কি c#? আমি এই হল c++যেমন xএকটি bool যেমন ফিরিয়ে দেওয়া হয়।
মারিয়ানো দেশানজে

1
আমি এটি সি ++ হিসাবে লিখেছি। এটি তৈরি করতে সি # তুচ্ছ: বুল isPow2 = ((x & ~ (x-1)) == এক্স)? x! = 0: মিথ্যা;
অ্যাবেলেঙ্কি

4

প্রদত্ত সংখ্যাটি 2 এর পাওয়ার কিনা তা সন্ধান করুন।

#include <math.h>

int main(void)
{
    int n,logval,powval;
    printf("Enter a number to find whether it is s power of 2\n");
    scanf("%d",&n);
    logval=log(n)/log(2);
    powval=pow(2,logval);

    if(powval==n)
        printf("The number is a power of 2");
    else
        printf("The number is not a power of 2");

    getch();
    return 0;
}

অথবা, সি # এ: রিটার্ন x == ম্যাথ.প্যাও (2, ম্যাথ.লগ (এক্স, 2));
কনফিগারকারী

4
ভাঙা। প্রধান ভাসমান পয়েন্ট গোলাকার সমস্যাগুলি থেকে ভুগছেন। আপনি ভাসমান পয়েন্ট ব্যবহার করতে চাইলে frexpবাজে logজিনিসগুলির চেয়ে ব্যবহার করুন ।
আর .. গীটহাব স্টপ হেল্পিং আইসিসি

4
bool isPowerOfTwo(int x_)
{
  register int bitpos, bitpos2;
  asm ("bsrl %1,%0": "+r" (bitpos):"rm" (x_));
  asm ("bsfl %1,%0": "+r" (bitpos2):"rm" (x_));
  return bitpos > 0 && bitpos == bitpos2;
}

4
int isPowerOfTwo(unsigned int x)
{
    return ((x != 0) && ((x & (~x + 1)) == x));
}

এটি সত্যিই দ্রুত। সমস্ত 2 ^ 32 পূর্ণসংখ্যার পরীক্ষা করতে এটি প্রায় 6 মিনিট এবং 43 সেকেন্ড সময় নেয়।


4
return ((x != 0) && !(x & (x - 1)));

যদি xদুটির শক্তি হয় তবে এর একক 1 বিট অবস্থানে রয়েছে n। এর অর্থ x – 1পজিশনে 0 রয়েছে n। কেন তা দেখতে, বাইনারি বিয়োগফল কীভাবে কাজ করে তা মনে করুন। যখন 1 থেকে বিয়োগ করে x, orrowণ অবস্থানের সমস্ত পথে প্রচার করে n; বিট n0 হয়ে যায় এবং সব নিম্ন বিট এখন 1. পরিণত, যেহেতু xসঙ্গে সাধারণ কোন 1 বিট হয়েছে x – 1, x & (x – 1)0, এবং !(x & (x – 1))সত্য।


3

একটি সংখ্যা 2 এর শক্তি, যদি এটিতে 1 সেট বিট থাকে। আমরা এই সম্পত্তি এবং জেনেরিক ফাংশনটি ব্যবহার করতে পারিcountSetBits যে কোনও সংখ্যা 2 এর পাওয়ার বা না তা খুঁজে বের করতে।

এটি একটি সি ++ প্রোগ্রাম:

int countSetBits(int n)
{
        int c = 0;
        while(n)
        {
                c += 1;
                n  = n & (n-1);
        }
        return c;
}

bool isPowerOfTwo(int n)
{        
        return (countSetBits(n)==1);
}
int main()
{
    int i, val[] = {0,1,2,3,4,5,15,16,22,32,38,64,70};
    for(i=0; i<sizeof(val)/sizeof(val[0]); i++)
        printf("Num:%d\tSet Bits:%d\t is power of two: %d\n",val[i], countSetBits(val[i]), isPowerOfTwo(val[i]));
    return 0;
}

আমাদের 0 0 এর 2 পাওয়ার হিসাবে স্পষ্টভাবে যাচাই করা দরকার না কারণ এটি 0 এর জন্যও মিথ্যা প্রদান করে।

আউটপুট

Num:0   Set Bits:0   is power of two: 0
Num:1   Set Bits:1   is power of two: 1
Num:2   Set Bits:1   is power of two: 1
Num:3   Set Bits:2   is power of two: 0
Num:4   Set Bits:1   is power of two: 1
Num:5   Set Bits:2   is power of two: 0
Num:15  Set Bits:4   is power of two: 0
Num:16  Set Bits:1   is power of two: 1
Num:22  Set Bits:3   is power of two: 0
Num:32  Set Bits:1   is power of two: 1
Num:38  Set Bits:3   is power of two: 0
Num:64  Set Bits:1   is power of two: 1
Num:70  Set Bits:3   is power of two: 0

ফাংশনটিতে 'উলং' টাইপের রিটার্ন থাকে তখন 'ইনট' হিসাবে সিটি ফেরত যায়? একটি whileপরিবর্তে একটি ব্যবহার করছেন if? আমি ব্যক্তিগতভাবে কোনও কারণ দেখতে পাচ্ছি না তবে এটি কার্যকর হবে বলে মনে হচ্ছে। সম্পাদনা: - না ... এটি এর চেয়ে বড় কোনও কিছুর জন্য 1 ফিরে আসবে 0!?
জেমস খুরি

@ জামেসখৌরি আমি একটি সি ++ প্রোগ্রাম লিখছিলাম তাই ভুল করে আমি একটি int পাঠিয়েছি returned তবে এটি একটি ছোট টাইপস ছিল এবং ডাউন ডাউনের প্রাপ্য ছিল না। তবে আমি আপনার মন্তব্যটির বাকী যুক্তিটি বুঝতে ব্যর্থ হয়েছি "যখন ব্যবহার করার পরিবর্তে" এবং "এটি 0 এর চেয়ে বড় কোনও কিছুর জন্য 1 প্রদান করবে"। আমি আউটপুট চেক করার জন্য প্রধান স্টাব যুক্ত করেছি। আফাইক এটির প্রত্যাশিত আউটপুট। আমি ভুল হলে আমাকে সংশোধন করুন।
জেরিহাউস

3

এক্ষেত্রে এর |পরিবর্তে ব্যবহার করে আমি অন্য একটি পদ্ধতি প্রণয়ন করেছি &:

bool is_power_of_2(ulong x) {
    if(x ==  (1 << (sizeof(ulong)*8 -1) ) return true;
    return (x > 0) && (x<<1 == (x|(x-1)) +1));
}

আপনার কি (x > 0)এখানে কিছুটা দরকার ?
কনফিগারকারী

@ কনফিগারুরেটর, হ্যাঁ, অন্যথায়_শক্তি_ফ_২ (০) সত্যই প্রত্যাবর্তন করবে
চেতন

3

2 এর যে কোনও শক্তির জন্য, নিম্নলিখিতগুলিও ধারণ করে।

এন & (- ঢ) == এন

দ্রষ্টব্য: এন = 0 এর জন্য ব্যর্থ, সুতরাং এটির জন্য এটি পরীক্ষা করা দরকার
কারণ এই কাজটি কেন কারণ:
-n এন এর 2s পরিপূরক। -n এর সাথে তুলনা করে এন এর ডানদিকের সেট বিটের বামে প্রতিটি বিট থাকবে। 2 এর শক্তির জন্য কেবল একটি সেট বিট থাকে।


2

উদাহরণ

0000 0001    Yes
0001 0001    No

অ্যালগরিদম

  1. একটি বিট মাস্ক ব্যবহার করে, NUMবাইনারি মধ্যে পরিবর্তনশীল বিভক্ত

  2. IF R > 0 AND L > 0: Return FALSE

  3. অন্যথায়, NUMশূন্য-না হওয়াতে পরিণত হয়

  4. IF NUM = 1: Return TRUE

  5. অন্যথায়, পদক্ষেপ 1 এ যান

জটিলতা

সময় ~ O(log(d))যেখানে dবাইনারি সংখ্যার সংখ্যা


1

বিট পাটিগণিত ছাড়াই @ ব্যবহারকারী 134548 এর উত্তর উন্নত করা:

public static bool IsPowerOfTwo(ulong n)
{
    if (n % 2 != 0) return false;  // is odd (can't be power of 2)

    double exp = Math.Log(n, 2);
    if (exp != Math.Floor(exp)) return false;  // if exp is not integer, n can't be power
    return Math.Pow(2, exp) == n;
}

এটি এর জন্য দুর্দান্ত কাজ করে:

IsPowerOfTwo(9223372036854775809)

ভাসমান পয়েন্ট অপারেশনগুলি একটি সাধারণ বিটওয়াইজ এক্সপ্রেশনের চেয়ে অনেক ধীরে ধীরে
ফুকলভ

1

মার্ক প্রস্তাব gravell এই যদি .NET কোর 3, আছে System.Runtime.Intrinsics.X86.Popcnt.PopCount

public bool IsPowerOfTwo(uint i)
{
    return Popcnt.PopCount(i) == 1
}

একক নির্দেশনা, দ্রুত তুলনায় (x != 0) && ((x & (x - 1)) == 0)কম পোর্টেবল।


আপনি কি নিশ্চিত যে এটি এর চেয়ে দ্রুততর (x != 0) && ((x & (x - 1)) == 0)? আমি যে সন্দেহ, esp। পুরানো সিস্টেমে যেখানে পপকেন্ট পাওয়া যায় না
ফুকলভ

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

উফফফ, আমি এটি আবার নিয়ে যাচ্ছি। আমি একটি লুপটিতে পরীক্ষা করছিলাম আমি মনে করি শাখার পূর্বাভাসটি "প্রতারণা" ছিল। পিওপিসিএনটি প্রকৃতপক্ষে একটি একক নির্দেশ যা একক ঘড়ির চক্রে চলে এবং আপনার যদি এটি উপলব্ধ থাকে তবে দ্রুত হয়।
এরাওল

0

সি তে, আমি i && !(i & (i - 1)কৌশলটি পরীক্ষা করেছি এবং এর সাথে তুলনা করেছি__builtin_popcount(i) , সিপিইউর পিওপিসিএনটি নির্দেশনা ব্যবহারের বিষয়ে নিশ্চিত হওয়ার জন্য লিনাক্সে জিসিসি ব্যবহার করে -mpopcnt পতাকা ব্যবহার করে। আমার পরীক্ষা প্রোগ্রামটি 0 এবং 2 ^ 31 এর মধ্যে পূর্ণসংখ্যার সংখ্যা গণনা করে যা দুটি একটি শক্তি।

প্রথমে আমি ভেবেছিলাম যে i && !(i & (i - 1)এটি 10% দ্রুত ছিল, যদিও আমি যাচাই করেছিলাম যে যেখানে আমি ব্যবহার করেছি সেখানকার ডিসপোজারে পিওপিসিএনটি ব্যবহার করা হয়েছিল__builtin_popcount

তবে, আমি বুঝতে পেরেছি যে আমি একটি বিবৃতি অন্তর্ভুক্ত করেছি এবং শাখার পূর্বাভাস সম্ভবত বিট টুইডলিং সংস্করণে আরও ভাল করছে। প্রত্যাশা অনুযায়ী আমি ইফ এবং পিওপিসিএনটি দ্রুত শেষ করেছি।

ফলাফল:

ইন্টেল (আর) কোর (টিএম) আই 7-4771 সিপিইউ সর্বাধিক 3.90GHz

Timing (i & !(i & (i - 1))) trick
30

real    0m13.804s
user    0m13.799s
sys     0m0.000s

Timing POPCNT
30

real    0m11.916s
user    0m11.916s
sys     0m0.000s

এএমডি রাইজেন থ্রেড্রিপার 2950X 16-কোর প্রসেসর সর্বাধিক 3.50GHz

Timing (i && !(i & (i - 1))) trick
30

real    0m13.675s
user    0m13.673s
sys 0m0.000s

Timing POPCNT
30

real    0m13.156s
user    0m13.153s
sys 0m0.000s

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

popcnt_test.c:

#include "stdio.h"

// Count # of integers that are powers of 2 up to 2^31;
int main() {
  int n;
  for (int z = 0; z < 20; z++){
      n = 0;
      for (unsigned long i = 0; i < 1<<30; i++) {
       #ifdef USE_POPCNT
        n += (__builtin_popcount(i)==1); // Was: if (__builtin_popcount(i) == 1) n++;
       #else
        n += (i && !(i & (i - 1)));  // Was: if (i && !(i & (i - 1))) n++;
       #endif
      }
  }

  printf("%d\n", n);
  return 0;
}

পরীক্ষা চালান:

gcc popcnt_test.c -O3 -o test.exe
gcc popcnt_test.c -O3 -DUSE_POPCNT -mpopcnt -o test-popcnt.exe

echo "Timing (i && !(i & (i - 1))) trick"
time ./test.exe

echo
echo "Timing POPCNT"
time ./test-opt.exe

-1
private static bool IsPowerOfTwo(ulong x)
{
    var l = Math.Log(x, 2);
    return (l == Math.Floor(l));
}

9223372036854775809 নম্বরটির জন্য এটি ব্যবহার করে দেখুন it এটি কি কাজ করে? আমি মনে করি না, গোলাকার ত্রুটির কারণে।
কনফিগারকারী

1
@ কনফিগুয়েটর 922337203685477580_9_ আমার কাছে 2 জনের মতো মনে হচ্ছে না;)
কিরস্টস্টেইন

1
@ কীর্স্টেস্টিন: এই সংখ্যাটি তাকে একটি মিথ্যা ইতিবাচক উপহার দিয়েছে।
এরিখ মীরাবলাল

7
কির্চস্টেইন: এটি আমার কাছে একটার মতো লাগে না। এটি ফাংশনটির মতো দেখতে দেখতে ...
কনফিগারকারী

-2

জাভাতে এই প্রোগ্রামটি যদি 2 এর শক্তি না হয় তবে "সত্য" প্রদান করে এবং 2 এর শক্তি না হলে "মিথ্যা" প্রদান করে returns

// To check if the given number is power of 2

import java.util.Scanner;

public class PowerOfTwo {
    int n;
    void solve() {
        while(true) {
//          To eleminate the odd numbers
            if((n%2)!= 0){
                System.out.println("false");
                break;
            }
//  Tracing the number back till 2
            n = n/2;
//  2/2 gives one so condition should be 1
            if(n == 1) {
                System.out.println("true");
                break;
            }
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in = new Scanner(System.in);
        PowerOfTwo obj = new PowerOfTwo();
        obj.n = in.nextInt();
        obj.solve();
    }

}

OUTPUT : 
34
false

16
true

1
এই প্রশ্নটিকে সি # ট্যাগ করা হয়েছে, এবং আগের সমাধানগুলির তুলনায় আপনার সমাধানটিও খুব ধীর গতির [
ফুচলভি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.