সংখ্যাটি সি ++ তে 2 এর শক্তি কিনা তা পরীক্ষা করার সহজ উপায় কী?


94

আমার এই জাতীয় ক্রিয়া দরকার:

// return true iff 'n' is a power of 2, e.g.
// is_power_of_2(16) => true  is_power_of_2(3) => false
bool is_power_of_2(int n);

কেউ কি পরামর্শ দিতে পারে আমি কীভাবে এটি লিখতে পারি? আপনি কি আমাকে একটি ভাল ওয়েবসাইট বলতে পারেন যেখানে এই ধরণের অ্যালগরিদম পাওয়া যাবে?



@ রুটট্রেভেলার - সম্ভবত কোনও সদৃশ নয়। সি ++ এবং জাভা বিভিন্ন ভাষা এবং প্রতিটি আলাদা আলাদা সুবিধা দেয়। উদাহরণস্বরূপ, সি / সি ++ এ আমরা এখন বিএমআই সক্ষম সক্রিয় প্রসেসরের সাথে ইন্টার্নিকগুলি ব্যবহার করতে পারি, যা একবার ঘড়ির মধ্যে তা করার জন্য মেশিনের নির্দেশ জারি করে। আমি ভাবছি জাভাতে অন্যান্য জিনিস রয়েছে যেমন ম্যাথের রুটিনের থেকে কিছু।
jww

উত্তর:


191

(n & (n - 1)) == 0ভাল. তবে নোট করুন যে এটি এন = 0 এর জন্য ভুলভাবে সত্য হয়ে যাবে, সুতরাং যদি এটি সম্ভব হয় তবে আপনি এটি পরিষ্কারভাবে পরীক্ষা করতে চাইবেন।

http://www.ographicics.stanford.edu/~seender/bithacks.html এর সাথে চতুর বিট-টুইডলিং অ্যালগরিদমগুলির একটি বৃহত সংগ্রহ রয়েছে।


8
তাই মূলত(n>0 && ((n & (n-1)) == 0))
সৌরভ গোয়েল

4
@ সৌরভগোয়াল বা n && !(n & (n - 1))উত্তরের লিঙ্ক হিসাবে বলা হয়েছে।
কার্স্টেন

কেন, ওহ কেন, এটি উত্তরের শীর্ষে নেই? ওপি দয়া করে গ্রহণ করুন।
অনর্থক

@SaurabhGoyal এক ছোট উন্নতি হল: n & !(n & (n - 1))। বিটওয়াইড এবং লক্ষ্য করুন &(যৌক্তিক নয় &&)। বিটওয়াইজ অপারেটররা সংক্ষিপ্ত সার্কিট প্রয়োগ করে না এবং তাই কোডটি শাখা করে না। শাখার ভুল অনুমানের সম্ভাবনা থাকতে পারে এবং এক্সপ্রেশনটির আরএইচ গণনা করার সময় এটি (যেমন !(n & (n - 1))) সস্তা This
ক্যাসিও নেড়ি

@ ক্যাসিও !একটি লজিকাল অপারেটর এবং অতএব !(n & (n - 1))বুলিয়ান এর মান হবে, আপনি কি নিশ্চিত যে একটি বুলিয়ান এবং একটি নম্বর কিছুটা বিটওয়াস এবং অপারেটরকে দেওয়া যেতে পারে? যদি হ্যাঁ, এটি দেখতে ভাল লাগছে।
সৌরভ গোয়াল

81

দু'জনের পাওয়ারের মধ্যে একটি বিট সেট থাকবে (স্বাক্ষরযুক্ত সংখ্যার জন্য)। কিছুটা এইরকম

bool powerOfTwo = !(x == 0) && !(x & (x - 1));

ঠিকঠাক কাজ করবে; দু'জনের পাওয়ারের চেয়ে কম এক হ'ল কম তাৎপর্যপূর্ণ বিটগুলিতে সমস্ত 1s হয়, সুতরাং অবশ্যই অবশ্যই 0 বিট দিকের দিকে।

যেহেতু আমি স্বাক্ষরবিহীন সংখ্যাগুলি ধরে নিচ্ছিলাম, == 0 পরীক্ষা (যা আমি মূলত ভুলে গেছি, দুঃখিত) যথেষ্ট পরিমাণে। আপনি স্বাক্ষরিত পূর্ণসংখ্যা ব্যবহার করতে পারলে আপনি একটি> 0 পরীক্ষা চাইতে পারেন।


আপনি একটি 'মিস করছি!' বা একটি '== 0'

এক্স এর নেতিবাচক মানের জন্য আপনি একটি পরীক্ষাও হারিয়ে ফেলছেন।
রব ওয়েলস

ঝরঝরে, আপনি 'সম্পাদিত x মিনিট আগে' প্রদর্শিত না করে কীভাবে এটি সম্পাদনা করলেন?

সিরিয়াসলি, আপনি কীভাবে 120 টি প্রখ্যাত প্রতিক্রিয়ার জন্য ভুল উত্তর পেয়েছিলেন?

@ মাইক এফ: প্রকৃতপক্ষে, দেখে মনে হচ্ছে লোকে উত্তরগুলি তাদের চেক না করেই ভোট দেবে। যে কেউ ভুল করতে পারে, আমার ধারণা - ভবিষ্যতে যদি আমি কিছু করি তবে এগুলি সম্পাদনা করতে নির্দ্বিধায় অনুভব করুন।
অ্যাডাম রাইট 15

49

বাইনারি দু'জনের শক্তি এর মতো দেখতে:

1: 0001
2: 0010
4: 0100
8: 1000

মনে রাখবেন যে সর্বদা ঠিক 1 বিট সেট থাকে। একমাত্র ব্যতিক্রম হ'ল একটি স্বাক্ষরিত পূর্ণসংখ্যার সাথে। উদাহরণস্বরূপ 8-বিট স্বাক্ষরিত পূর্ণসংখ্যার সাথে -128 এর মান মনে হচ্ছে:

10000000

সুতরাং শূন্যের চেয়ে সংখ্যাটি বড় কিনা তা যাচাই করার পরে, আমরা এটি পরীক্ষা করতে একটি চতুর সামান্য বিট হ্যাক ব্যবহার করতে পারি এবং এটি কেবলমাত্র একটি বিট সেট করা আছে।

bool is_power_of_2(int x) {
    return x > 0 && !(x & (x−1));
}

আরও কিছু বিড়ম্বনার জন্য এখানে দেখুন


14

পন্থা # 1:

এটি পরীক্ষা করার জন্য সংখ্যাটি 2 দিয়ে ভাগ করুন।

সময়ের জটিলতা: ও (লগ 2 এন)।

পদ্ধতির # 2:

বিটওয়াইস এবং তার ঠিক আগের নম্বর সহ সংখ্যাটি শূন্যের সমান হওয়া উচিত।

উদাহরণ: সংখ্যা = 8 বাইনারি 8: 1 0 0 0 বাইনারি 7: 0 1 1 1 এবং বিটওয়াইড এবং উভয় সংখ্যার 0 0 0 0 = 0 হয়।

সময়ের জটিলতা: ও (1)।

পদ্ধতির # 3:

বিটওয়াইজ এক্সওর এর ঠিক পূর্ববর্তী সংখ্যার সাথে উভয় সংখ্যার যোগফল হওয়া উচিত।

উদাহরণ: সংখ্যা = 8 বাইনারি 8: 1 0 0 0 বাইনারি 7: 0 1 1 1 এবং উভয় সংখ্যার বিটওয়াইজ এক্সওআর 1 1 1 1 = 15 is

সময়ের জটিলতা: ও (1)।

http://javaexplorer03.blogspot.in/2016/01/how-to-check-number-is-power-of-two.html



7

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

এন এবং (- এন) == এন

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



এই এন-স্বাক্ষর না থাকলে ঘটে যাওয়া রূপান্তরগুলির সাথে কাজ করে?
জোসেফ গারভিন

6

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

if(1==__builtin_popcount(n))

নাহ। আমি শুধু এটি পরীক্ষা করেছি। আমি পপকাউন্ট পছন্দ করি তবে পাওয়ার-অফ -২ পরীক্ষার জন্য, পরীক্ষাটি i && !(i & (i - 1)))আমার মেশিনে প্রায় 10% দ্রুততর হয়, এমনকি আমি যখন সিসিএসে নেটিভ এসেম্বলি পিওপিসিএনটি নির্দেশকে সক্ষম করার বিষয়ে নিশ্চিত ছিলাম।
ইউরোল

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

5

সি ++ ২০ তে এমন কিছু রয়েছে std::ispow2যা আপনি নিজেরাই এটি বাস্তবায়নের প্রয়োজন না হলে আপনি এই উদ্দেশ্যটির জন্য ব্যবহার করতে পারেন:

#include <bit>
static_assert(std::ispow2(16));
static_assert(!std::ispow2(15));

3

নিম্নলিখিতটি দ্রুততর হবে তবে বুলিয়ান শর্ট সার্কিটের কারণে তুলনাটি ধীরগতির কারণে সর্বাধিক আপ-ভোট দেওয়া উত্তর।

int isPowerOfTwo(unsigned int x)
{
  return x && !(x & (x – 1));
}

আপনি যদি জানেন যে এক্সটি 0 নাও হতে পারে

int isPowerOfTwo(unsigned int x)
{
  return !(x & (x – 1));
}


3

সংখ্যাটি সি ++ তে 2 এর শক্তি কিনা তা পরীক্ষা করার সহজ উপায় কী?

যদি আপনার কাছে বিট ম্যানিপুলেশন নির্দেশাবলী সহ একটি আধুনিক ইন্টেল প্রসেসর থাকে তবে আপনি নিম্নলিখিতগুলি সম্পাদন করতে পারেন। এটি সরল সি / সি ++ কোড বাদ দেয় কারণ অন্যরা ইতিমধ্যে এর উত্তর দিয়েছে, তবে বিএমআই উপলব্ধ না থাকলে বা সক্ষম না থাকলে আপনার এটি দরকার।

bool IsPowerOf2_32(uint32_t x)
{
#if __BMI__ || ((_MSC_VER >= 1900) && defined(__AVX2__))
    return !!((x > 0) && _blsr_u32(x));
#endif
    // Fallback to C/C++ code
}

bool IsPowerOf2_64(uint64_t x)
{
#if __BMI__ || ((_MSC_VER >= 1900) && defined(__AVX2__))
    return !!((x > 0) && _blsr_u64(x));
#endif
    // Fallback to C/C++ code
}

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

আমি সাধারণত পাহারা _blsr_u64একটি সঙ্গে _LP64_i686 উপর ক্ষেত্রে কম্পাইল। ঝাঁকুনির জন্য একটু পরিশ্রমের প্রয়োজন কারণ এটি কিছুটা আলাদা অভ্যন্তরীণ প্রতীক ব্যবহার করে:

#if defined(__GNUC__) && defined(__BMI__)
# if defined(__clang__)
#  ifndef _tzcnt_u32
#   define _tzcnt_u32(x) __tzcnt_u32(x)
#  endif
#  ifndef _blsr_u32
#    define  _blsr_u32(x)  __blsr_u32(x)
#  endif
#  ifdef __x86_64__
#   ifndef _tzcnt_u64
#    define _tzcnt_u64(x) __tzcnt_u64(x)
#   endif
#   ifndef _blsr_u64
#     define  _blsr_u64(x)  __blsr_u64(x)
#   endif
#  endif  // x86_64
# endif  // Clang
#endif  // GNUC and BMI

আপনি কি আমাকে একটি ভাল ওয়েবসাইট বলতে পারেন যেখানে এই ধরণের অ্যালগরিদম পাওয়া যাবে?

এই ওয়েবসাইটটি প্রায়শই উদ্ধৃত করা হয়: বিট টুইডলিং হ্যাকস


ওপিতে অনুরোধ করা এটি অবশ্যই "সহজতম উপায়" নয়, তবে নির্দিষ্ট পরিবেশের জন্য তর্কাতীতভাবে দ্রুততম। বিভিন্ন আর্কিটেকচারের জন্য কীভাবে শর্তসাপেক্ষী করা যায় তা দেখানো দুর্দান্তভাবে দরকারী।
নির্ভীক_ফুল

1

এটি সবচেয়ে দ্রুত বা সংক্ষিপ্ততম উপায় নয় তবে আমি মনে করি এটি খুব পঠনযোগ্য। সুতরাং আমি এই জাতীয় কিছু করব:

bool is_power_of_2(int n)
  int bitCounter=0;
  while(n) {
    if ((n & 1) == 1) {
      ++bitCounter;
    }
    n >>= 1;
  }
  return (bitCounter == 1);
}

বাইনারি দুটি শক্তির উপর ভিত্তি করে এটি কাজ করে। কেবলমাত্র একটি বিট সেট সহ যে কোনও সংখ্যা অবশ্যই দুটি এর শক্তি হতে পারে।


এটি দ্রুত বা সংক্ষিপ্ত নাও হতে পারে তবে শীর্ষের উত্তরের তুলনায় এটি সঠিক।

4
মন্তব্য করার সময় তারা সবাই বগড হয়ে গিয়েছিল। এগুলি তখন থেকে একটি গ্রহণযোগ্য রাষ্ট্র হিসাবে সম্পাদিত হয়েছে।

0

এক্ষেত্রে এর |পরিবর্তে আরও একটি পদ্ধতি ব্যবহার করা হচ্ছে &:

bool is_power_of_2(int x) {
    return x > 0 && (x<<1 == (x|(x-1)) +1));
}

0

এটি সি ++ এর মাধ্যমে সম্ভব

int IsPowOf2(int z) {
double x=log2(z);
int y=x;
if (x==(double)y)
return 1;
else
return 0;
}

4
এটি আমার কাছে সহজ বা দ্রুত নয়।
luk32

4
অর্থাৎ এটি সম্ভবত দ্রুত কারণে না log2, এবং প্রমাণ করে যে এটি কাজ করে যা ব্যাখ্যা করা এত সহজ নয় (অবশ্যই, আপনি গোলাকার ত্রুটির দ্বারা ধরা পেতে পারেন?) এটি অকারণে সংঘবদ্ধও হয় if..return..else..return। এটিকে ভেঙে ফেলাতে কী সমস্যা return x==(double)y;? এটি boolযেভাবেই ফেরত দেওয়া উচিত । আইএমও এমনকি টেরিনারি অপারেটর যদি আরও দৃ .়ভাবে আঁকতে চায় তবে আরও পরিষ্কার হবে int
luk32

0

আমি জানি এটি একটি খুব পুরানো পোস্ট, তবে আমি ভেবেছিলাম এটি এখানে পোস্ট করা আকর্ষণীয় হতে পারে।


থেকে কোড-গলফ দঃপূঃ (তাই একটির (অনেকগুলির) এই লিখেছেন সব ক্রেডিট): ভাষা শোকেস

( সি সম্পর্কে অনুচ্ছেদ , সাব-অনুচ্ছেদ দৈর্ঘ্য 36 স্নিপেট )

bool isPow2(const unsigned int num){return!!num&!(num&(num-1));}

-1

আর যাওয়ার উপায় (সম্ভবত দ্রুত নয়) এটি নির্ধারণ করা হয়েছে যে ln (x) / ln (2) একটি সম্পূর্ণ সংখ্যা কিনা।


4
এটি সম্পর্কে হয়তো নেই :-)।
paxdiablo

4
এটিতে ভাসমান পয়েন্টের অসম্পূর্ণতা নিয়ে সমস্যা হবে। ln (1 << 29) / ln (2) 29.000000000000004 এ আসে।
বেনামে

-3

এটি টি-এসকিউএল (এসকিউএল সার্ভার) এর বিট শিফট পদ্ধতি:

SELECT CASE WHEN @X>0 AND (@X) & (@X-1)=0 THEN 1 ELSE 0 END AS IsPowerOfTwo

এটি চারবার লোগারিদম করার চেয়ে অনেক দ্রুত (দশমিক ফলাফল পাওয়ার জন্য প্রথম সেট, পূর্ণসংখ্যার সেট পেতে এবং তুলনা করার জন্য ২ য় সেট)


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

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