2 की अगली शक्ति तक गोलाई


187

मैं एक फ़ंक्शन लिखना चाहता हूं जो 2 नंबर की निकटतम अगली शक्ति लौटाता है। उदाहरण के लिए यदि मेरा इनपुट 789 है, तो आउटपुट 1024 होना चाहिए। क्या बिना किसी लूप का उपयोग किए इसे प्राप्त करने का कोई तरीका है, लेकिन केवल कुछ बिटवाइज़ ऑपरेटरों का उपयोग करना है?


4
संभावित समाधानों के लिए यहां देखें: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2Float
स्टीफन

4
स्पष्टीकरण के माध्यम से, क्या आपको 2 की निकटतम शक्ति की आवश्यकता है (यानी 65 आपको 64 देगा, लेकिन 100 आपको 128 देगा) या सबसे ऊपर (यानी 65 आपको 128 देगा, और इसलिए 100)?
किम रीस

1
वे इस एक मिलान से अधिक प्रश्न कर रहे हैं। उदाहरण के लिए: stackoverflow.com/questions/364985/…
Yann Droneaud


7
@ नथन आपका लिंक इस सवाल से 8 महीने बाद का है।
जोसेफ क्विन्से

जवाबों:


146

बिट ट्विडलिंग हैक्स की जाँच करें । आपको आधार 2 लघुगणक प्राप्त करने की आवश्यकता है, फिर उसमें 1 जोड़ें। 32-बिट मान के लिए उदाहरण:

2 की अगली उच्चतम शक्ति तक गोल करें

unsigned int v; // compute the next highest power of 2 of 32-bit v

v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;

अन्य चौड़ाई का विस्तार स्पष्ट होना चाहिए।


11
यह सबसे कुशल समाधान नहीं है क्योंकि कई प्रोसेसर के पास अग्रणी शून्य गणना के लिए विशेष निर्देश है जो लॉग 2 को बहुत कुशलता से गणना करने के लिए उपयोग किया जा सकता है। En.wikipedia.org/wiki/Find_first_set
सिमोन

7
@ साइमन: यह पोर्टेबल समाधान है। सभी आर्किटेक्चर के लिए कोई भी सामान्य कुशल एल्गोरिथ्म नहीं है
phuclv

5
क्या होगा यदि संख्या स्वयं दो की शक्ति है?
लेवरम

5
यह धागा अभी भी अच्छी तरह से संदर्भित है लेकिन यह उत्तर (और अधिकांश अन्य) अत्यधिक पुराना है। सीपीयू को इसमें मदद करने का निर्देश है (वास्तव में उस समय पहले से?)। प्रेषक: jameshfisher.com/2018/03/30/round-up-power-2.html uint64_t next_pow2(uint64_t x) { return x == 1 ? 1 : 1<<(64-__builtin_clzl(x-1)); } और 32 बिट के लिए: uint32_t next_pow2(uint32_t x) { return x == 1 ? 1 : 1<<(32-__builtin_clz(x-1)); }यदि आप GCC का उपयोग करते हैं (और मुझे लगता है?), लेकिन यह समय लेने के लिए बुद्धिमान होगा? चारों ओर सभी विकल्पों को कॉपी-पेस्ट करने के बजाय CLZ पर कॉल करें।
मैप्पमा

2
@MappaM यह उत्तर अभी भी अत्यधिक प्रासंगिक है और इसे करने के लिए सबसे अच्छा पोर्टेबल तरीका है। आपके 64-बिट संस्करण में अपरिभाषित व्यवहार होता है यदि x > UINT32_MAXवह शाखा रहित नहीं है। इसके अलावा, -mtune=genericडिफ़ॉल्ट रूप से जीसीसी और क्लैंग उपयोग करते हैं (जैसा कि अधिकांश डिस्ट्रोस करते हैं), इसलिए आपका कोड lzcntx86_64 पर निर्देश तक विस्तारित नहीं होगा - यह वास्तव में कुछ MUCH धीमी (एक libgcc रूटीन) तक विस्तारित होगा जब तक कि आप कुछ का उपयोग नहीं करते -march=native। इसलिए आपका प्रस्तावित प्रतिस्थापन गैर-पोर्टेबल, छोटी गाड़ी और (आमतौर पर) धीमा है।
क्रेग बार्न्स

76
next = pow(2, ceil(log(x)/log(2)));

यह आपको x पाने के लिए 2 नंबर बढ़ाकर मिल जाता है (संख्या का लॉग लें, और वांछित आधार के लॉग द्वारा विभाजित करें, अधिक के लिए विकिपीडिया देखें ) द्वारा काम करता है। फिर निकटतम पूर्ण शक्ति प्राप्त करने के लिए छत के साथ गोल करें।

यह एक और सामान्य उद्देश्य है (यानी धीमा!) बिटवाइड तरीकों की तुलना में कहीं और जुड़ा हुआ है, लेकिन गणित को जानने के लिए अच्छा है, एह?


3
C99 से, आप केवल लॉग 2 का उपयोग कर सकते हैं यदि आपके टूल द्वारा समर्थित है। जीसीसी और वीएस नहीं लगता है :(
मैथ्यू पढ़ें

2
आपको एक ब्रैकेट याद आ रहा है ... अगला = pow (2, ceil (log (x) / log (2)));
Matthieu Cormier

13
फ्लोट सटीकता के बारे में सावधान रहें, हालांकि। log(pow(2,29))/log(2)= 29.000000000000004, इसलिए परिणाम 2 29 को वापस करने के बजाय 2 30 है । मुझे लगता है कि यही कारण है कि log2 फ़ंक्शन मौजूद हैं?
एंडोलिथ

46
इसकी लागत संभवतः कम से कम 200 चक्र है और यह सही भी नहीं है। यह इतने सारे उत्थान क्यों करता है?
एक्सल गेटिंग

4
@SuperflyJon लेकिन इसमें बिटवाइज़ ऑपरेटरों का उल्लेख है और मुझे लगता है कि शुद्धता किसी भी प्रश्न से निहित है जब तक कि अन्यथा नोट न किया गया हो।
ब्लैकजैक

50
unsigned long upper_power_of_two(unsigned long v)
{
    v--;
    v |= v >> 1;
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;
    v++;
    return v;

}

62
अच्छा होगा यदि आपने इसे जिम्मेदार ठहराया है (जब तक कि आपने इसकी खोज नहीं की है)। यह बिट ट्विगलिंग हैक्स पेज से आता है।
फ्लोरीन

3
क्या यह 32-बिट संख्या के लिए है? 64-बिट के लिए एक्सटेंशन?
जोनाथन लेफ्लर

जोनाथन, आपको इसे ऊपरी आधे हिस्से के लिए करने की आवश्यकता है, और यदि यह शून्य है, तो आप इसे निचले आधे हिस्से के लिए करते हैं।
फ्लोरिन

5
@florin, यदि v एक 64-बिट प्रकार है, तो क्या आप 16 में से एक के बाद "c | = v >> 32" नहीं जोड़ सकते?
इवान टेरान

3
कोड जो केवल एक विशिष्ट बिट चौड़ाई के लिए काम करता है, न्यूनतम-चौड़ाई प्रकारों के बजाय निश्चित-चौड़ाई प्रकारों का उपयोग करना चाहिए। इस फ़ंक्शन को लेना चाहिए और वापस लौटना चाहिए uint32_t
क्रेग बार्न्स

50

मुझे लगता है कि यह भी काम करता है:

int power = 1;
while(power < x)
    power*=2;

और जवाब है power


19
पर्याप्त सवाल निष्पक्ष कोई छोरों के लिए कहा। लेकिन कुछ अन्य कार्यों के रूप में चतुर, कोड के लिए है कि प्रदर्शन संवेदनशील नहीं है जवाब है कि जल्दी और आसानी से समझा और सही होने के लिए सत्यापित है हमेशा मेरे लिए जीतता है।
टिम एमबी

2
यह 2 की निकटतम शक्ति को वापस नहीं कर रहा है, उस की बट्टे की शक्ति एक्स की तुलना में तुरंत बड़ी है। अभी भी बहुत अच्छा है
कॉफिडेवलर

1
गुणा करने के बजाय, कुछ बिटवाइज़ "मैजिक" का उपयोग किया जा सकता हैpower <<= 1
vallentin

5
@ वालेंटिन जो एक संकलक द्वारा स्वचालित रूप से अनुकूलित किया जाना चाहिए।
मार्कवेस्टन

4
अनंत लूप से सावधान रहें यदि xबहुत बड़ा है (यानी 2 की अगली शक्ति का प्रतिनिधित्व करने के लिए पर्याप्त बिट्स नहीं)।
अल्बान

36

यदि आप GCC का उपयोग कर रहे हैं, तो आप लॉकलेस इंक द्वारा next_pow2 () फ़ंक्शन को ऑप्टिमाइज़ करने पर एक नज़र डाल सकते हैं .. यह पृष्ठ बिल्ट-इन फ़ंक्शन builtin_clz()(अग्रणी शून्य की गणना) और बाद में सीधे x86 (ia32) का उपयोग करने का एक तरीका बताता है कोडांतरक अनुदेश bsr(रिवर्स बिट स्कैन), जैसा कि वह में वर्णित एक और जवाब के gamedev साइट का लिंक । यह कोड पिछले उत्तर में वर्णित लोगों की तुलना में तेज़ हो सकता है ।

वैसे, यदि आप असेंबलर इंस्ट्रक्शन और 64 बिट डेटा टाइप का उपयोग नहीं करने जा रहे हैं, तो आप इसका उपयोग कर सकते हैं

/**
 * return the smallest power of two value
 * greater than x
 *
 * Input range:  [2..2147483648]
 * Output range: [2..2147483648]
 *
 */
__attribute__ ((const))
static inline uint32_t p2(uint32_t x)
{
#if 0
    assert(x > 1);
    assert(x <= ((UINT32_MAX/2) + 1));
#endif

    return 1 << (32 - __builtin_clz (x - 1));
}

3
ध्यान दें कि यह 2 की सबसे छोटी शक्ति को x के बराबर या उससे अधिक देता है। X (x -1) को x में बदलने से x की तुलना में 2 की छोटी शक्ति को वापस करने के लिए फ़ंक्शन बदल जाता है।
गिलियूम

2
आप _BitScanForwardदृश्य C ++
KindDragon

आप इसका उपयोग भी कर सकते हैं__builtin_ctz()
Mark

@MarkP __builtin_ctz()दो की अगली शक्ति तक 2 नंबर की किसी भी गैर-शक्ति को गोल करने के लिए उपयोगी नहीं होगा
यान ड्रोन्यूड

2
कृपया अपने उत्तर में अन्य संकलक के लिए निर्मित बिटकॉइन कार्यों की विकिपीडिया सूची के लिए एक लिंक जोड़ें: en.wikipedia.org/wiki/Find_first_set#Tool_and_library_support                                कृपया 64-बिट संस्करण भी प्रदान करें। मैं निम्नलिखित C ++ 11 फ़ंक्शन का प्रस्ताव करता हूं:              constexpr uint64_t nextPowerOfTwo64 (uint64_t x) { return 1ULL<<(sizeof(uint64_t) * 8 - __builtin_clzll(x)); }
olibre

15

एक और, यद्यपि मैं चक्र का उपयोग करता हूं, लेकिन गणित के ऑपरेंड की तुलना में यह बहुत तेज है

दो "मंजिल" विकल्प की शक्ति:

int power = 1;
while (x >>= 1) power <<= 1;

दो "छत" विकल्प की शक्ति:

int power = 2;
x--;    // <<-- UPDATED
while (x >>= 1) power <<= 1;

अपडेट करें

जैसा कि टिप्पणियों में उल्लेख किया गया था कि ceilजहां गलती हुई उसका परिणाम गलत था।

यहाँ पूर्ण कार्य हैं:

unsigned power_floor(unsigned x) {
    int power = 1;
    while (x >>= 1) power <<= 1;
    return power;
}

unsigned power_ceil(unsigned x) {
    if (x <= 1) return 1;
    int power = 2;
    x--;
    while (x >>= 1) power <<= 1;
    return power;
}

2
परिणाम सही नहीं है यदि xबिजली की शक्ति 2. परीक्षण करने के लिए एक सूक्ष्म यदि इनपुट की शक्ति 2 की आवश्यकता है। #define ISPOW2(x) ((x) > 0 && !((x) & (x-1)))
pgplus1628 13

@zorksylar अधिक कुशलता से होगाif (x == 0) return 1; /* Or 0 (Which is what I use) */ x--; /* Rest of program */
yyny

अच्छा समाधान! लेकिन power of two "ceil" optionयह सही नहीं है। उदाहरण के लिए, जब x = 2परिणाम होना चाहिए 2बजाय4
MZD

10

किसी भी अहस्ताक्षरित प्रकार के लिए, बिट ट्विडलिंग हैक्स पर निर्माण:

#include <climits>
#include <type_traits>

template <typename UnsignedType>
UnsignedType round_up_to_power_of_2(UnsignedType v) {
  static_assert(std::is_unsigned<UnsignedType>::value, "Only works for unsigned types");
  v--;
  for (size_t i = 1; i < sizeof(v) * CHAR_BIT; i *= 2) //Prefer size_t "Warning comparison between signed and unsigned integer"
  {
    v |= v >> i;
  }
  return ++v;
}

वहाँ वास्तव में एक लूप नहीं है क्योंकि संकलक संकलन समय की संख्या पर जानता है।


4
ध्यान दें कि प्रश्न सी। के बारे में है
मार्टिंक्यूनेव

@martinkunev बस अनइंस्टॉल टाइप बदलें और इसे मैन्युअल रूप से संसाधित करें। मुझे पूरा यकीन है कि एक सी प्रोग्रामर इस सरल टेम्पलेट का विस्तार करते हुए विस्तार कर सकता है std::is_unsigned<UnsignedType>::value
user877329

2
@ user877329 निश्चित रूप से, जावास्क्रिप्ट में एक उत्तर के रूप में अच्छी तरह से करना अच्छा होगा, बस अगर कोई व्यक्ति सी। में अनुवाद करना चाहता है
Martinkunev

जावास्क्रिप्ट में @martinkunev UnsignedType? वैसे भी, यह समाधान दिखाता है कि इसे किसी भी UnsignType के लिए कैसे करना है, और यह C ++ में लिखा जाना है, बजाय pseudocode [sizeof (v) * CHAR_BIT के बजाय कुछ ऐसा है जो UnsignedType के किसी ऑब्जेक्ट में बिट्स की संख्या की तरह है]।
user877329

9

IEEE फ़्लोट्स के लिए आप ऐसा कुछ कर पाएंगे।

int next_power_of_two(float a_F){
    int f = *(int*)&a_F;
    int b = f << 9 != 0; // If we're a power of two this is 0, otherwise this is 1

    f >>= 23; // remove factional part of floating point number
    f -= 127; // subtract 127 (the bias) from the exponent

    // adds one to the exponent if were not a power of two, 
    // then raises our new exponent to the power of two again.
    return (1 << (f + b)); 
}

यदि आपको पूर्णांक समाधान की आवश्यकता है और आप इनलाइन असेंबली का उपयोग करने में सक्षम हैं, तो बीएसआर आपको x86 पर पूर्णांक का लॉग 2 देगा। यह गिनता है कि कितने सही बिट सेट हैं, जो उस नंबर के लॉग 2 के बराबर है। अन्य प्रोसेसर में समान निर्देश (अक्सर) होते हैं, जैसे कि सीएलजेड और आपके कंपाइलर के आधार पर आपके लिए काम करने के लिए एक आंतरिक उपलब्ध हो सकता है।


यह एक दिलचस्प एक घटना है जो प्रश्न से संबंधित नहीं है (मैं केवल पूर्णांकों को राउंडऑफ़ करना चाहता हूं), इस एक को आज़माऊंगा ..
नवीन

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

यह सख्त अलियासिंग नियमों को तोड़ता है। कुछ कंपाइलरों पर यह काम नहीं कर सकता है या चेतावनी जारी नहीं कर सकता है।
martinkunev

6

प्रश्न के बावजूद cयहाँ मेरे पाँच सेंट के रूप में टैग किया गया है। हमें भाग्यशाली, C ++ 20 शामिल होगा std::ceil2और std::floor2( यहां देखें )। यह consexprटेम्प्लेट फ़ंक्शंस, करंट है जीसीसी कार्यान्वयन बिटशफ्टिंग का उपयोग करता है और किसी भी अभिन्न अहस्ताक्षरित प्रकार के साथ काम करता है।


2
उन्होंने हाल ही में इसका नाम बदलकर bit_ceil ओपन-std.org/JTC1/SC22/WG21/docs/papers/2020/p1956r1.pdf
वोल्फगैंग

5
/*
** http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
*/
#define __LOG2A(s) ((s &0xffffffff00000000) ? (32 +__LOG2B(s >>32)): (__LOG2B(s)))
#define __LOG2B(s) ((s &0xffff0000)         ? (16 +__LOG2C(s >>16)): (__LOG2C(s)))
#define __LOG2C(s) ((s &0xff00)             ? (8  +__LOG2D(s >>8)) : (__LOG2D(s)))
#define __LOG2D(s) ((s &0xf0)               ? (4  +__LOG2E(s >>4)) : (__LOG2E(s)))
#define __LOG2E(s) ((s &0xc)                ? (2  +__LOG2F(s >>2)) : (__LOG2F(s)))
#define __LOG2F(s) ((s &0x2)                ? (1)                  : (0))

#define LOG2_UINT64 __LOG2A
#define LOG2_UINT32 __LOG2B
#define LOG2_UINT16 __LOG2C
#define LOG2_UINT8  __LOG2D

static inline uint64_t
next_power_of_2(uint64_t i)
{
#if defined(__GNUC__)
    return 1UL <<(1 +(63 -__builtin_clzl(i -1)));
#else
    i =i -1;
    i =LOG2_UINT64(i);
    return 1UL <<(1 +i);
#endif
}

यदि आप अपरिभाषित व्यवहार के दायरे में उद्यम नहीं करना चाहते हैं, तो इनपुट मूल्य 1 और 2 ^ 63 के बीच होना चाहिए। संकलन समय पर स्थिरांक स्थापित करने के लिए मैक्रो भी उपयोगी है।


यह संभवतः सबसे खराब समाधान है (यह 64-बिट निरंतर पर ULL प्रत्यय को याद कर रहा है)। यह सभी मामलों में प्रति इनपुट 32 परीक्षण उत्पन्न करेगा। थोड़ी देर के लूप का उपयोग करने के लिए बेहतर है, यह हमेशा तेज या उसी गति से होगा।
xryl669

1
लेकिन ... यह पूर्वप्रक्रमक द्वारा मूल्यांकन किया जा सकता है यदि इनपुट एक स्थिर है, और इस प्रकार रन समय में शून्य संचालन!
माइकल

4

पूर्णता के लिए यहां बोग-मानक C में एक फ्लोटिंग-पॉइंट कार्यान्वयन है।

double next_power_of_two(double value) {
    int exp;
    if(frexp(value, &exp) == 0.5) {
        // Omit this case to round precise powers of two up to the *next* power
        return value;
    }
    return ldexp(1.0, exp);
}

1
रैंडम ब्राउज़र, यदि आप इस टिप्पणी को पढ़ते हैं, तो इस कोड को चुनें। यह स्पष्ट रूप से सबसे अच्छा उत्तर है, कोई विशेष निर्देश नहीं, कोई थोड़ा चक्कर नहीं, बस कुशल, पोर्टेबल और मानक कोड। यह अनुमान
लगाते हुए

5
रैंडम ब्राउज़र, यह धीमी गति से मृत होने वाला है यदि आपके पास विशेष फ़्लोटिंग पॉइंट हार्डवेयर नहीं है। X86 पर आप इस कोड के चारों ओर बिट ट्विडलिंग का उपयोग करके हलकों को चला सकते हैं। rep bsr ecx,eax; mov eax,0; cmovnz eax,2; shl eax,clलगभग 25x तेज है।
जोहान

4

एक कुशल Microsoft (जैसे, Visual Studio 2017) पूर्णांक इनपुट के लिए C / C ++ में विशिष्ट समाधान। इनपुट के मामले को सबसे महत्वपूर्ण 1 बिट के स्थान की जांच करने से पहले दो मूल्य की शक्ति के मिलान से घटाकर नियंत्रित करता है।

inline unsigned int ExpandToPowerOf2(unsigned int Value)
{
    unsigned long Index;
    _BitScanReverse(&Index, Value - 1);
    return (1U << (Index + 1));
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#if defined(WIN64) // The _BitScanReverse64 intrinsic is only available for 64 bit builds because it depends on x64

inline unsigned long long ExpandToPowerOf2(unsigned long long Value)
{
    unsigned long Index;
    _BitScanReverse64(&Index, Value - 1);
    return (1ULL << (Index + 1));
}

#endif

यह निम्नलिखित के समान इंटेल प्रोसेसर के लिए 5 या तो इनलाइन निर्देश उत्पन्न करता है:

dec eax
bsr rcx, rax
inc ecx
mov eax, 1
shl rax, cl

जाहिरा तौर पर विजुअल स्टूडियो सी ++ कंपाइलर को संकलन-समय मूल्यों के लिए इसे अनुकूलित करने के लिए कोडित नहीं किया गया है, लेकिन ऐसा नहीं है कि वहां बहुत सारे निर्देश हैं।

संपादित करें:

यदि आप 1 से 1 (2 से शून्य शक्ति) का इनपुट मान चाहते हैं, तो उपरोक्त कोड के लिए एक छोटा संशोधन अभी भी बिना किसी शाखा के निर्देशों के सीधे उत्पन्न होता है।

inline unsigned int ExpandToPowerOf2(unsigned int Value)
{
    unsigned long Index;
    _BitScanReverse(&Index, --Value);
    if (Value == 0)
        Index = (unsigned long) -1;
    return (1U << (Index + 1));
}

केवल कुछ और निर्देश उत्पन्न करता है। चाल यह है कि सूचकांक को एक परीक्षण द्वारा प्रतिस्थापित किया जा सकता है जिसके बाद एक cmove निर्देश दिया जाता है।


एक छोटी सी गलती: इसे 1 के लिए 1 वापस करना चाहिए, हालांकि यह नहीं है।
अक्टूबर को 0kcats

धन्यवाद। जिस एप्लिकेशन के लिए इसे विकसित किया गया था, उसमें 1 इनपुट होने पर हमें स्पष्ट रूप से 2 से पहली शक्ति की आवश्यकता थी। 1 एक विशेष मामले के रूप में सशर्त के साथ लिया जा सकता है बिना बहुत अधिक निर्देशों के मैं कल्पना करता हूं।
NoelC

1 के इनपुट मान के लिए 1 रिटर्न करने वाले संस्करण को शामिल करने के लिए उत्तर अपडेट करें
NoelC

3

X86 में आप sse4 बिट मैनिपुलेशन निर्देशों का उपयोग इसे तेज करने के लिए कर सकते हैं।

//assume input is in eax
popcnt edx,eax
lzcnt ecx,eax
cmp edx,1
jle @done       //popcnt says its a power of 2, return input unchanged
mov eax,2
shl eax,cl
@done: rep ret

सी में आप मिलान आंतरिक का उपयोग कर सकते हैं।


बेकार लेकिन भयानक!
मार्को

3

यहाँ सी में मेरा समाधान है। आशा है कि यह मदद करता है!

int next_power_of_two(int n) {
    int i = 0;
    for (--n; n > 0; n >>= 1) {
        i++;
    }
    return 1 << i;
}

0

कई प्रोसेसर आर्किटेक्चर समर्थन log base 2या बहुत समान ऑपरेशन - count leading zeros। कई संकलक इसके लिए आंतरिक हैं। Https://en.wikipedia.org/wiki/Find_first_set देखें


यह उच्चतम सेट बिट (= bsr) या अग्रणी शून्य गणना के बारे में नहीं है। वह 2. की निकटतम शक्ति तक गोल करना चाहता है । "घटाना 1, फिर bsr और पाली 1 छोड़ दिया" के साथ उत्तर ऐसा करता है।
फ़्लो

0

मान लें कि आपके पास एक अच्छा संकलक है और यह इस बिंदु पर मेरे ऊपर हाथ से पहले थोड़ा सा चक्कर लगा सकता है, लेकिन वैसे भी यह काम करता है !!!

    // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
    #define SH1(v)  ((v-1) | ((v-1) >> 1))            // accidently came up w/ this...
    #define SH2(v)  ((v) | ((v) >> 2))
    #define SH4(v)  ((v) | ((v) >> 4))
    #define SH8(v)  ((v) | ((v) >> 8))
    #define SH16(v) ((v) | ((v) >> 16))
    #define OP(v) (SH16(SH8(SH4(SH2(SH1(v))))))         

    #define CB0(v)   ((v) - (((v) >> 1) & 0x55555555))
    #define CB1(v)   (((v) & 0x33333333) + (((v) >> 2) & 0x33333333))
    #define CB2(v)   ((((v) + ((v) >> 4) & 0xF0F0F0F) * 0x1010101) >> 24)
    #define CBSET(v) (CB2(CB1(CB0((v)))))
    #define FLOG2(v) (CBSET(OP(v)))

नीचे दिए गए टेस्ट कोड:

#include <iostream>

using namespace std;

// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
#define SH1(v)  ((v-1) | ((v-1) >> 1))  // accidently guess this...
#define SH2(v)  ((v) | ((v) >> 2))
#define SH4(v)  ((v) | ((v) >> 4))
#define SH8(v)  ((v) | ((v) >> 8))
#define SH16(v) ((v) | ((v) >> 16))
#define OP(v) (SH16(SH8(SH4(SH2(SH1(v))))))         

#define CB0(v)   ((v) - (((v) >> 1) & 0x55555555))
#define CB1(v)   (((v) & 0x33333333) + (((v) >> 2) & 0x33333333))
#define CB2(v)   ((((v) + ((v) >> 4) & 0xF0F0F0F) * 0x1010101) >> 24)
#define CBSET(v) (CB2(CB1(CB0((v)))))
#define FLOG2(v) (CBSET(OP(v))) 

#define SZ4         FLOG2(4)
#define SZ6         FLOG2(6)
#define SZ7         FLOG2(7)
#define SZ8         FLOG2(8) 
#define SZ9         FLOG2(9)
#define SZ16        FLOG2(16)
#define SZ17        FLOG2(17)
#define SZ127       FLOG2(127)
#define SZ1023      FLOG2(1023)
#define SZ1024      FLOG2(1024)
#define SZ2_17      FLOG2((1ul << 17))  // 
#define SZ_LOG2     FLOG2(SZ)

#define DBG_PRINT(x) do { std::printf("Line:%-4d" "  %10s = %-10d\n", __LINE__, #x, x); } while(0);

uint32_t arrTble[FLOG2(63)];

int main(){
    int8_t n;

    DBG_PRINT(SZ4);    
    DBG_PRINT(SZ6);    
    DBG_PRINT(SZ7);    
    DBG_PRINT(SZ8);    
    DBG_PRINT(SZ9); 
    DBG_PRINT(SZ16);
    DBG_PRINT(SZ17);
    DBG_PRINT(SZ127);
    DBG_PRINT(SZ1023);
    DBG_PRINT(SZ1024);
    DBG_PRINT(SZ2_17);

    return(0);
}

आउटपुट:

Line:39           SZ4 = 2
Line:40           SZ6 = 3
Line:41           SZ7 = 3
Line:42           SZ8 = 3
Line:43           SZ9 = 4
Line:44          SZ16 = 4
Line:45          SZ17 = 5
Line:46         SZ127 = 7
Line:47        SZ1023 = 10
Line:48        SZ1024 = 10
Line:49        SZ2_16 = 17

0

मैं 2 की निकटतम कम शक्ति प्राप्त करने की कोशिश कर रहा हूं और इस फ़ंक्शन को बनाया है। यह आपकी मदद कर सकता है। बस निकटतम 2 की ऊपरी शक्ति प्राप्त करने के लिए निकटतम संख्या 2 को गुणा करें

int nearest_upper_power(int number){
    int temp=number;
    while((number&(number-1))!=0){
        temp<<=1;
        number&=temp;
    }
    //Here number is closest lower power 
    number*=2;
    return number;
}

0

एक्सेल में पॉल डिक्सन के उत्तर को अपनाया, यह पूरी तरह से काम करता है।

 =POWER(2,CEILING.MATH(LOG(A1)/LOG(2)))

0

x==1केवल x86 प्लेटफॉर्म, कंपाइलर, gcc या क्लैंग के लिए @YannDroneaud उत्तर का एक प्रकार मान्य है :

__attribute__ ((const))
static inline uint32_t p2(uint32_t x)
{
#if 0
    assert(x > 0);
    assert(x <= ((UINT32_MAX/2) + 1));
#endif
  int clz;
  uint32_t xm1 = x-1;
  asm(
    "lzcnt %1,%0"
    :"=r" (clz)
    :"rm" (xm1)
    :"cc"
    );
    return 1 << (32 - clz);
}

0

यहाँ है कि मैं क्या उपयोग कर रहा हूँ यह एक स्थिर अभिव्यक्ति है, अगर इनपुट एक निरंतर अभिव्यक्ति है।

#define uptopow2_0(v) ((v) - 1)
#define uptopow2_1(v) (uptopow2_0(v) | uptopow2_0(v) >> 1)
#define uptopow2_2(v) (uptopow2_1(v) | uptopow2_1(v) >> 2)
#define uptopow2_3(v) (uptopow2_2(v) | uptopow2_2(v) >> 4)
#define uptopow2_4(v) (uptopow2_3(v) | uptopow2_3(v) >> 8)
#define uptopow2_5(v) (uptopow2_4(v) | uptopow2_4(v) >> 16)

#define uptopow2(v) (uptopow2_5(v) + 1)  /* this is the one programmer uses */

उदाहरण के लिए, एक अभिव्यक्ति जैसे:

uptopow2(sizeof (struct foo))

अच्छी तरह से एक स्थिर करने के लिए कम हो जाएगा।


0

आपको अपने उद्देश्य के लिए सहायक होने के लिए निम्नलिखित स्पष्टीकरण मिल सकता है:


0

इसे एक फ्लोट में कनवर्ट करें और फिर .hex () का उपयोग करें जो सामान्यीकृत IEEE प्रतिनिधित्व दिखाता है।

>>> float(789).hex() '0x1.8a80000000000p+9'

फिर बस घातांक निकालें और 1 जोड़ें।

>>> int(float(789).hex().split('p+')[1]) + 1 10

और इस शक्ति को 2 बढ़ाएं।

>>> 2 ** (int(float(789).hex().split('p+')[1]) + 1) 1024


ध्यान दें कि यह उत्तर अजगर में है
डेविड वैलेस

0
import sys


def is_power2(x):
    return x > 0 and ((x & (x - 1)) == 0)


def find_nearest_power2(x):
    if x <= 0:
        raise ValueError("invalid input")
    if is_power2(x):
        return x
    else:
        bits = get_bits(x)
        upper = 1 << (bits)
        lower = 1 << (bits - 1)
        mid = (upper + lower) // 2
        if (x - mid) > 0:
            return upper
        else:
            return lower


def get_bits(x):
    """return number of bits in binary representation"""
    if x < 0:
        raise ValueError("invalid input: input should be positive integer")
    count = 0
    while (x != 0):
        try:
            x = x >> 1
        except TypeError as error:
            print(error, "input should be of type integer")
            sys.exit(1)
        count += 1
    return count

-1

यदि आपको OpenGL से संबंधित सामान की आवश्यकता है:

/* Compute the nearest power of 2 number that is 
 * less than or equal to the value passed in. 
 */
static GLuint 
nearestPower( GLuint value )
{
    int i = 1;

    if (value == 0) return -1;      /* Error! */
    for (;;) {
         if (value == 1) return i;
         else if (value == 3) return i*4;
         value >>= 1; i *= 2;
    }
}

8
'फॉर' एक लूप है।
फ्लोरिन

1
florin: यह है। और यह यहाँ एक पाश के रूप में प्रयोग किया जाता है, है ना?
तमस Czinege

9
DrJokepu - मुझे लगता है कि फ्लोरीन यहाँ कहने का मतलब है कि ओपी ने लूप-कम समाधान के लिए कहा
एली बेन्द्स्की 5

-1

यदि आप एक लाइन-टेम्पलेट चाहते हैं। यह रहा

int nxt_po2(int n) { return 1 + (n|=(n|=(n|=(n|=(n|=(n-=1)>>1)>>2)>>4)>>8)>>16); }

या

int nxt_po2(int n) { return 1 + (n|=(n|=(n|=(n|=(n|=(n-=1)>>(1<<0))>>(1<<1))>>(1<<2))>>(1<<3))>>(1<<4)); }

यह C या C ++ में अपरिभाषित व्यवहार है और त्रुटियों को जन्म देगा। nअनुक्रम बिंदु के बिना कई बार संशोधित करना अमान्य है। आपने इसे ऐसे लिखा है जैसे n-=1पहले होना चाहिए लेकिन यहाँ केवल यही गारंटी है कि और nउसके बाद उसका नया मूल्य समाहित ;न हो जाए।
सैम होसेवर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.