यह जांचने का सबसे सरल तरीका है कि क्या कोई संख्या C ++ में 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);

क्या कोई सुझाव दे सकता है कि मैं यह कैसे लिख सकता हूं? क्या आप मुझे एक अच्छी वेब साइट बता सकते हैं जहाँ इस तरह का एल्गोरिदम मिल सकता है?



@rootTraveller - शायद कोई डुप्लिकेट नहीं है। C ++ और Java अलग-अलग भाषाएं हैं और प्रत्येक अलग-अलग सुविधाएं प्रदान करता है। उदाहरण के लिए, C / C ++ में हम अब BMI इनेबल्ड प्रोसेसर के साथ इंट्रिंसिक्स का उपयोग कर सकते हैं, जो मशीन निर्देश को एक ही बार में करने के लिए जारी करता है। मुझे लगता है कि जावा में अन्य चीजें हैं, जैसे कि शायद मैथ रूटीन से कुछ।
jww

जवाबों:


190

(n & (n - 1)) == 0श्रेष्ठ है। हालांकि, ध्यान दें कि यह गलत तरीके से n = 0 के लिए सही लौटेगा, इसलिए यदि यह संभव है, तो आप इसके लिए स्पष्ट रूप से जांचना चाहेंगे।

http://www.graphics.stanford.edu/~seander/bithacks.html में इस सहित चतुर बिट-ट्विडलिंग एल्गोरिदम का एक बड़ा संग्रह है।


8
इसलिए मूल रूप से(n>0 && ((n & (n-1)) == 0))
सौरभ गोयल

1
@ सौरभ गोयल या n && !(n & (n - 1))उत्तर राज्यों के भीतर लिंक के रूप में।
कार्स्टन

क्यों, ओह क्यों, यह जवाब के शीर्ष पर नहीं है? ओपी कृपया स्वीकार करें।
16urn में

@SaurabhGoyal एक छोटा सा सुधार यह है: n & !(n & (n - 1))। बिटवाइज़ और &(तार्किक नहीं &&) और को नोटिस करें । बिटवाइज़ ऑपरेटर्स शॉर्ट सर्किटिंग लागू नहीं करते हैं और इसलिए, कोड शाखा नहीं करता है। यह उन स्थितियों में बेहतर है, जहां शाखा की गलतफहमी होने की संभावना है और जब अभिव्यक्ति के आरएच की गणना की जाती है (यानी !(n & (n - 1))) सस्ता है।
कैसियो नेरी

@ कैसियो !एक तार्किक ऑपरेटर है और इसलिए इसका मूल्य !(n & (n - 1))एक बूलियन होगा, क्या आप सुनिश्चित हैं कि एक बूलियन और एक नंबर एक बिटवाइज़ और ऑपरेटर को दिया जा सकता है? यदि हाँ, यह अच्छा लग रहा है।
सौरभ गोयल

81

दो की शक्ति में केवल एक बिट सेट (अहस्ताक्षरित संख्या के लिए) होगा। कुछ इस तरह

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

ठीक काम करेगा; दो में से एक कम से कम महत्वपूर्ण बिट्स में दो की शक्ति है, इसलिए और 0 से बिटवाइज़ तक होना चाहिए।

जैसा कि मैं अहस्ताक्षरित संख्या मान रहा था, == 0 परीक्षण (कि मैं मूल रूप से भूल गया, क्षमा करें) पर्याप्त है। यदि आप हस्ताक्षर किए गए पूर्णांक का उपयोग कर रहे हैं, तो आप एक 0 परीक्षण कर सकते हैं।


आप एक 'याद आ रही है!' या '== 0'

तुम भी एक्स के नकारात्मक मूल्य के लिए एक परीक्षण याद कर रहे हैं।
रोब वेल्स

नीट, आपने 'संपादित एक्स मिनट पहले' को प्रदर्शित किए बिना इसे कैसे संपादित किया?

गंभीरता से, आप एक निस्तेज गलत उत्तर के लिए सिर्फ 120 प्रतिनिधि कैसे प्राप्त कर सकते हैं?

@ माइक एफ: वास्तव में, ऐसा लगता है कि लोग जवाबों की जांच किए बिना वोट देंगे। कोई भी गलती कर सकता है, मुझे लगता है - अगर मैं भविष्य में कोई भी बनाता हूं, तो उन्हें बाहर संपादित करने के लिए स्वतंत्र महसूस करें।
एडम राइट

49

बाइनरी में दो की शक्तियां इस तरह दिखती हैं:

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

ध्यान दें कि हमेशा 1 बिट सेट होता है। एकमात्र अपवाद एक हस्ताक्षरित पूर्णांक के साथ है। जैसे -128 के मान के साथ एक 8-बिट हस्ताक्षरित पूर्णांक ऐसा लगता है:

10000000

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

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

अधिक बिट के लिए यहाँ देखें ।


14

दृष्टिकोण # 1:

इसकी जांच के लिए संख्या को 2 पुनरावृत्ति से विभाजित करें।

समय जटिलता: O (log2n)।

दृष्टिकोण # 2:

बिटवाइज़ और इसकी पिछली संख्या के साथ संख्या ZERO के बराबर होनी चाहिए।

उदाहरण: संख्या = 8 8 का बाइनरी: 1 0 0 0 7 का बाइनरी: 0 1 1 1 और दोनों संख्याओं का बिटवाइस और 0 0 0 0 = 0 है।

समय जटिलता: ओ (1)।

दृष्टिकोण # 3:

बिटवॉइर XOR अपने पिछले नंबर के साथ संख्या दोनों संख्याओं का योग होना चाहिए।

उदाहरण: संख्या = 8 8 का बाइनरी: 1 0 0 0 7 का बाइनरी: 0 1 1 1 और दोनों संख्याओं का बिटवाइज XOR 1 1 1 1 = 15 है।

समय जटिलता: ओ (1)।

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



7

2 की किसी भी शक्ति के लिए, निम्नलिखित भी रखती है।

n & (- एन) == n

नोट: यह स्थिति n = 0 के लिए सही है, हालांकि इसकी कोई शक्ति नहीं है। 2.
क्यों यह काम करता है:
-n n का पूरक 2 है। -n में n की तुलना में फ़्लिप n के सबसे दाहिने सेट बिट के बाईं ओर हर बिट होगा। 2 की शक्तियों के लिए केवल एक सेट बिट है।


2
मेरा मतलब है कि स्थिति n = 0 के लिए सही है, हालांकि इसकी दो की शक्ति नहीं है
FReeze FRancis

क्या यह रूपांतरणों के साथ काम करता है यदि n अहस्ताक्षरित है?
जोसफ गार्विन

5

C ++ 20 में वह है std::ispow2जिसे आप इस उद्देश्य के लिए उपयोग कर सकते हैं यदि आपको इसे स्वयं लागू करने की आवश्यकता नहीं है:

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

5

जीसीसी का उपयोग करते हुए, यह शायद सबसे तेज़ है। यह केवल एक POPCNT सीपीयू अनुदेश और एक तुलना का उपयोग करता है। 2 नंबर की किसी भी शक्ति का द्विआधारी प्रतिनिधित्व, हमेशा केवल एक बिट सेट होता है, अन्य बिट्स हमेशा शून्य होते हैं। इसलिए हम POPCNT के साथ सेट बिट्स की संख्या की गणना करते हैं, और यदि यह 1 के बराबर है, तो संख्या 2 की शक्ति है। मुझे नहीं लगता कि कोई भी तेज तरीके संभव हैं। और यह बहुत आसान है, अगर आप इसे एक बार समझ गए:

if(1==__builtin_popcount(n))

नहीं। मैंने अभी यह परीक्षण किया है। मुझे पॉपकाउंट बहुत पसंद है, लेकिन पावर -2 के परीक्षण के लिए, i && !(i & (i - 1)))मेरी मशीन पर परीक्षण लगभग 10% तेज है, यहां तक ​​कि जब मैं जीसीसी में देशी विधानसभा पीओपीसीएनटी अनुदेश को सक्षम करने के लिए निश्चित था।
युगपुरुष

उफ़ मैं इसे वापस लेता हूं। मेरा परीक्षण कार्यक्रम एक लूप में चल रहा था और शाखा की भविष्यवाणी "धोखा" थी। आप सही हैं, यदि आपके पास अपने सीपीयू पर POPCNT निर्देश है तो यह तेज है।
युगपुरुष

3

बाद में तेजी से होगा, फिर बूलियन शॉर्ट-सर्कुलेटिंग और तथ्य यह है कि तुलना धीमी है के कारण अधिकांश अप-वोटेड जवाब।

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

यदि आप जानते हैं कि x 0 नहीं हो सकता है

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


3

यह जांचने का सबसे सरल तरीका है कि क्या कोई संख्या C ++ में 2 की शक्ति है?

यदि आपके पास बिट मैनिपुलेशन निर्देश के साथ एक आधुनिक इंटेल प्रोसेसर है , तो आप निम्नलिखित कार्य कर सकते हैं। यह सीधे C / C ++ कोड को छोड़ देता है क्योंकि अन्य लोग पहले ही इसका उत्तर दे चुके हैं, लेकिन बीएमआई उपलब्ध या सक्षम नहीं होने पर आपको इसकी आवश्यकता है।

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__। यह Visual Studio 2015 और इसके बाद के संस्करण में AVX2 उपलब्ध और सक्षम होने पर Microsoft कंपाइलर में उपलब्ध है । आपके द्वारा आवश्यक हेडर के लिए, SIMD आंतरिक के लिए हेडर फ़ाइलें देखें ।

मैं आमतौर पर i686 पर संकलित मामले के _blsr_u64साथ गार्ड करता हूं _LP64_। क्लैंग को थोड़ा वर्कअराउंड की आवश्यकता होती है क्योंकि यह एक अलग आंतरिक आंतरिक प्रतीक नाम का उपयोग करता है:

#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

क्या आप मुझे एक अच्छी वेब साइट बता सकते हैं जहाँ इस तरह का एल्गोरिदम मिल सकता है?

इस वेबसाइट को अक्सर उद्धृत किया जाता है: बिट ट्विडलिंग हैक्स


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

1

यह सबसे तेज़ या सबसे छोटा तरीका नहीं है, लेकिन मुझे लगता है कि यह बहुत पठनीय है। तो मैं कुछ ऐसा करूंगा:

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

यह काम करता है क्योंकि बाइनरी दो की शक्तियों पर आधारित है। केवल एक बिट सेट के साथ कोई भी संख्या दो की शक्ति होनी चाहिए।


यह तेज़ या छोटा नहीं हो सकता है, लेकिन यह शीर्ष उत्तरों के विपरीत सही है।

2
टिप्पणी के समय वे सभी बिगड़े हुए थे। तब से उन्हें स्वीकार्य स्थिति में संपादित किया गया है।

0

यहाँ एक और तरीका है, इस मामले में |इसके बजाय का उपयोग कर &:

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

0

यह c ++ के माध्यम से संभव है

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

2
मेरे लिए यह न तो सरल है, न ही तेज।
लुक 32

2
यानी यह निश्चित रूप से उपवास के कारण नहीं है log2, और सबूत है कि यह काम करता है यह व्याख्या करना इतना आसान नहीं है (ठीक है, क्या आप गोल त्रुटियों के साथ पकड़े जा सकते हैं?)। यह भी अनावश्यक रूप से जटिल है if..return..else..return। इसे ढहाने में क्या गलत है return x==(double)y;? इसे किसी भी प्रकार से लौटाना चाहिए bool। IMO भी ternary ऑपरेटर स्पष्ट होगा अगर कोई वास्तव में छड़ी करना चाहता है int
luk32

0

मुझे पता है कि यह बहुत पुरानी पोस्ट है, लेकिन मुझे लगा कि यहां इसे पोस्ट करना दिलचस्प हो सकता है।


से कोड-गोल्फ एसई (ताकि एक (रों) ने लिखा है यह करने के लिए सभी क्रेडिट): बोली का शोकेस

( सी के बारे में पैराग्राफ , उप- अनुच्छेद लंबाई 36 स्निपेट )

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

-1

जाने का दूसरा तरीका (शायद सबसे तेज़ नहीं) यह निर्धारित करना है कि ln (x) / ln (2) एक पूरी संख्या है।


2
इसके बारे में शायद कोई बात नहीं है :-)।
paxdiablo

1
इससे फ्लोटिंग पॉइंट अशुद्धि के साथ समस्या होगी। 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

यह चार बार लघुगणक करने की तुलना में बहुत तेज़ है (दशमलव परिणाम प्राप्त करने के लिए पहला सेट, पूर्णांक सेट और सेट प्राप्त करने के लिए 2 सेट)


5
यह देखना अच्छा है कि इस प्रश्न का शीर्ष उत्तर टी-एसक्यूएल में कैसे लागू किया जा सकता है, लेकिन यह वास्तव में यहां पूछे गए प्रश्न के लिए प्रासंगिक नहीं है। एक विकल्प (यदि आप टी-एसक्यूएल में समाधान की तलाश कर रहे थे, तो यह उत्तर दिया गया प्रश्न पाया गया, इसे टी-एसक्यूएल में लागू किया और सोचा कि यह उत्तर पोस्ट करना काफी दिलचस्प होगा) टी-एसक्यूएल के संदर्भ में प्रश्न को पोस्ट करना होगा, फिर इस उत्तर वाले प्रश्न के संदर्भ में, स्वयं इसका उत्तर दें। आशा है कि यह सुझाव मददगार होगा।
साइमन

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