2 এর পরবর্তী পাওয়ার পর্যন্ত বৃত্তাকার


188

আমি একটি ফাংশন লিখতে চাই যা 2 সংখ্যার নিকটতম পরবর্তী পাওয়ারটি দেয়। উদাহরণস্বরূপ যদি আমার ইনপুটটি 789 হয় তবে আউটপুট 1024 হওয়া উচিত any কোনও লুপ ব্যবহার না করে কেবল কিছু বিটওয়াইস অপারেটর ব্যবহার না করে এটি অর্জনের কোনও উপায় আছে কি?


4
সম্ভাব্য সমাধানের জন্য এখানে দেখুন: http://ographicics.stanford.edu/~seender/bithacks.html#RoundUpPowerOf2Float
স্টেফান

4
স্পষ্টকরণের মাধ্যমে, আপনার কি নিকটতম শক্তি প্রয়োজন 2 (যেমন 65 আপনাকে 64 দেয়, তবে 100 আপনাকে 128 দেবে) বা উপরের নিকটতম (অর্থাত 65 আপনাকে 128 দেবে, এবং 100) কী হবে?
কিম রিস

1
এগুলির সাথে মিলে যাওয়া তারা একাধিক প্রশ্ন। উদাহরণস্বরূপ: stackoverflow.com/questions/364985/...
Yann Droneaud


7
@ নাথান আপনার লিঙ্কটি এই প্রশ্নের চেয়ে 8 মাস পরে
জোসেফ কুইনসে

উত্তর:


147

বিট টুইডলিং হ্যাকগুলি পরীক্ষা করুন । আপনার বেস 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.wikedia.org/wiki/Find_first_set
সাইমন

7
@ সিমন: এটি বহনযোগ্য সমাধান। সমস্ত আর্কিটেকচারের জন্য কোনও সাধারণ দক্ষ অ্যালগরিদম নেই
ফুক্লভ

5
সংখ্যাটি নিজেই যদি দুজনের শক্তি হয় তবে কী হবে?
লাইটেরাম

5
এই থ্রেডটি এখনও ভালভাবে উল্লেখ করা হয়েছে তবে এই উত্তরটি (এবং বেশিরভাগ অন্যান্য) অত্যন্ত পুরানো highly এটি সহায়তা করার জন্য সিপিইউগুলির একটি নির্দেশনা রয়েছে (আসলে ইতিমধ্যে সেই সময়ে?) থেকে: 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)); }এটি হ'ল আপনি যদি জিসিসি (এবং কলং আমি ভাবি?) ব্যবহার করেন তবে সময়টি গ্রহণ করা বুদ্ধিমানের কাজ হবে চারপাশের সমস্ত বিকল্পের কপি-পেস্ট করার পরিবর্তে সিএলজেডে কল সন্ধান করুন।
ম্যাপাপে

2
@ ম্যাপম এই উত্তরটি এখনও অত্যন্ত প্রাসঙ্গিক এবং এটি করার সর্বোত্তম পোর্টেবল উপায়। আপনার -৪-বিট সংস্করণটি x > UINT32_MAXশাখাবিহীন না থাকলে আচরণের সংজ্ঞা নির্ধারণ করে । এছাড়াও, জিসিসি এবং ক্ল্যাং -mtune=genericডিফল্টরূপে ব্যবহার করে (যেমন বেশিরভাগ ডিস্ট্রো করে) তাই আপনার কোডটি lzcntx86_64- র নির্দেশে প্রসারিত হবে না - যদি আপনি এর মতো কিছু না ব্যবহার করেন তবে এটি আসলে অনেক ধীর গতিতে (একটি libgcc রুটিন) প্রসারিত হবে -march=native। সুতরাং আপনার প্রস্তাবিত প্রতিস্থাপনটি অ-বহনযোগ্য, বগি এবং (সাধারণত) ধীর er
ক্রেগ বার্নস

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

এটি x পেতে আপনি 2 সংখ্যা বাড়িয়েছেন তা খুঁজে বের করে কাজ করে (সংখ্যার লগ নিতে এবং পছন্দসই বেসের লগ দ্বারা ভাগ করুন, আরও উইকিপিডিয়া দেখুন )। তারপরে সিলের সাহায্যে নিকটস্থ পুরো নম্বর পাওয়ার পাওয়ার জন্য এটি গোল করুন।

এটি অন্য কোথাও যুক্ত বিটওয়াইজ পদ্ধতিগুলির চেয়ে আরও সাধারণ উদ্দেশ্য (অর্থাত্ ধীর!) পদ্ধতি, তবে গণিতগুলি জানা ভাল, তাই না?


3
C99 থেকে, আপনি কেবল নিজের সরঞ্জামগুলি দ্বারা সমর্থিত হলে লগ 2 ব্যবহার করতে পারেন। জিসিসি এবং ভিএস বলে মনে হচ্ছে না :(
ম্যাথু

2
আপনি একটি বন্ধনী মিস করছেন ... পরের = পাও (2, সিল (লগ (এক্স) / লগ (2)));
ম্যাথিউউ কর্মিয়ার

13
যদিও ভাসমান নির্ভুলতার বিষয়ে সতর্ক থাকুন। log(pow(2,29))/log(2)= 29.000000000000004, সুতরাং ফলাফল 2 29 ফেরতের পরিবর্তে 2 30 হয় I আমার মনে হয় এই কারণেই লগ 2 ফাংশন বিদ্যমান?
এন্ডোলিথ

46
এর ব্যয় সম্ভবত কমপক্ষে 200 চক্র এবং এটি এমনকি সঠিক নয়। এটি কেন এত উপার্জন করে?
অ্যাক্সেল Gneiting

4
@ সুফ্প্লি জোন তবে এতে বিটওয়াইজ অপারেটরদের উল্লেখ রয়েছে এবং আমি ধরে নিয়েছি যে অন্যথায় উল্লেখ না করা হলে কোনও প্রশ্ন দ্বারা নির্ভুলতা বোঝানো হয়েছে।
ব্ল্যাকজ্যাক 16

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
@ ফ্লোরিন, যদি ভি 64৪-বিট টাইপ হয় তবে আপনি কি ১ 16 এর জন্য একটি "সি | = ভি >> 32" যুক্ত করতে পারবেন না?
ইভান তেরান

3
যে কোডটি কেবল একটি নির্দিষ্ট বিট প্রস্থের জন্য কাজ করে সেগুলি ন্যূনতম-প্রস্থের প্রকারের পরিবর্তে স্থির-প্রস্থের প্রকারগুলি ব্যবহার করা উচিত। এই ফাংশনটি নেওয়া উচিত এবং ফিরে আসা উচিত uint32_t
ক্রেগ বার্নস

50

আমি এটিও কাজ করে বলে মনে করি:

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

এবং উত্তরটি হ'ল power


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

2
এটি 2 এর নিকটতম শক্তিটি ফিরিয়ে দিচ্ছে না, এর বুথ পাওয়ার এক্স এর চেয়ে তাত্পর্যপূর্ণভাবে বড় Still এখনও খুব ভাল
কফডেপলবার

1
গুণফলের পরিবর্তে কিছুটা power <<= 1
বিস্মৃতভাবে

5
@ ভালেনটিন এটি একটি সংকলক দ্বারা স্বয়ংক্রিয়ভাবে অনুকূলিত হওয়া উচিত।
মার্ক ওয়েস্টন

4
অসম্পূর্ণ লুপ থেকে সাবধান থাকুন যদি xখুব বড় হয় (যেমন 2 এর পরবর্তী শক্তির প্রতিনিধিত্ব করার জন্য পর্যাপ্ত বিট নয়)।
আলবান

36

আপনি জিসিসি ব্যবহার করেন, তাহলে আপনি কটাক্ষপাত আছে করতে চাইতে পারেন next_pow2 () ফাংশন অপ্টিমাইজ Lockless Inc দ্বারা .. এই পৃষ্ঠাটি ব্যবহার করুন একটি উপায় বর্ণনা বিল্ট-ইন ফাংশন builtin_clz()(শূন্য COUNT) এবং পরে সরাসরি এক্স 86 ব্যবহার করুন (ia32) assembler নির্দেশ 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
নোট করুন যে এটি x এর চেয়ে ও ও বড় সমান 2 এর ক্ষুদ্রতম পাওয়ারটি প্রদান করে। (X -1) কে x তে পরিবর্তন করা ফাংশনকে x এর চেয়ে 2 এর বৃহত্তর শক্তি ফেরত দেয়।
গিলাইম

2
আপনি _BitScanForwardভিজ্যুয়াল সি ++
KindDragon

আপনি এটি ব্যবহার করতে পারেন__builtin_ctz()
মার্কপি

@ মার্কপি 2 টির __builtin_ctz()কোনও অ-
পাওয়ারকে

2
দয়া করে আপনার উত্তরে অন্যান্য সংকলকগুলির জন্য বিল্টিন বিটওয়াইস ফাংশনগুলির উইকিপিডিয়া তালিকার একটি লিঙ্ক যুক্ত                                করুন : এন.ইউইকিপিডিয়া.org / উইকি / ফাইন্ড_ফাইস্ট_সেট # টুল_অ্যান্ডলিবারি_সম্পোর্ট দয়া করে একটি -৪ -বিট সংস্করণও সরবরাহ করুন। আমি নিম্নলিখিত সি ++ 11 ফাংশনটি প্রস্তাব করছি:              constexpr uint64_t nextPowerOfTwo64 (uint64_t x) { return 1ULL<<(sizeof(uint64_t) * 8 - __builtin_clzll(x)); }
ওলিব্রে

15

আরও একটি, যদিও আমি চক্র ব্যবহার করি, তবে এটি গণিতের অপারেন্ডগুলির চেয়ে অনেক দ্রুত

দুটি "তল" বিকল্পের শক্তি:

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

দুটি "সিল" বিকল্পের শক্তি:

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

হালনাগাদ

মন্তব্যে যেমন উল্লেখ করা হয়েছে সেখানে ceilফলাফল ছিল যেখানে ভুল ছিল mistake

এখানে সম্পূর্ণ ফাংশন রয়েছে:

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
x2 পাওয়ার হলে ফলাফলটি সঠিক হয় না input ইনপুট 2 এর পাওয়ার হয় কিনা তা পরীক্ষা করতে একটি মাইক্রো। #define ISPOW2(x) ((x) > 0 && !((x) & (x-1)))
pgplus1628

@ জোর্কসিলার আরও দক্ষতার সাথে হবেif (x == 0) return 1; /* Or 0 (Which is what I use) */ x--; /* Rest of program */
ইয়াই

ভাল সমাধান! তবে এটি power of two "ceil" optionসঠিক নয়। উদাহরণস্বরূপ, যখন x = 224
ফলাফলটির

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
নোট করুন যে প্রশ্নটি সি সম্পর্কে
মার্টিনকুনেভ

@ মার্টিংকুনেভ কেবল স্বাক্ষরযুক্ত টাইপ প্রতিস্থাপন করুন এবং ম্যানুয়ালি এটি প্রক্রিয়া করুন। আমি প্রায় নিশ্চিত একটি সি প্রোগ্রামার উপেক্ষা এই সহজ ফর্মা প্রসারিত পাবেনা আমি std::is_unsigned<UnsignedType>::valueকথন।
ব্যবহারকারী 87737329

2
@ ব্যবহারকারী 73737329২২ অবশ্যই, জাভাস্ক্রিপ্টেও উত্তর পেয়ে ভাল লাগবে, ঠিক যদি কেউ
সিটিতে

জাভাস্ক্রিপ্টে @ মার্টিনকিউনভ স্বাক্ষরিত টাইপ? যাইহোক, এই সমাধানটি কীভাবে কোনও স্বাক্ষরযুক্ত টাইপের জন্য এটি করতে হয় তা সিউডকোড [সাইজফ (ভি) * সিএনএইচআরআইটি-টাইপ এর অবজেক্টে বিটের সংখ্যার মতো কিছু না করে] লিখতে হবে।
ব্যবহারকারীর 877329

9

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

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 এর ঠিক সমান। অন্যান্য প্রসেসরের একই নির্দেশাবলী রয়েছে (প্রায়শই) যেমন সিএলজেড এবং আপনার সংকলকটির উপর নির্ভর করে আপনার জন্য কাজ করার জন্য কোনও অন্তর্নিহিত উপস্থিত থাকতে পারে।


এটি একটি আকর্ষণীয় ঘটনা, যা প্রশ্নের সাথে সম্পর্কিত নয় (আমি কেবলমাত্র পূর্ণসংখ্যার বৃত্তান্ত করতে চাই), এটি চেষ্টা করে দেখুন ..
নবীন

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

এটি কঠোর আলিয়াজিং বিধি ভঙ্গ করে। কিছু সংকলকগুলিতে এটি কাজ করতে বা সতর্কতা জারি করতে পারে না।
মার্টিনকুনেভ

6

প্রশ্ন থাকা সত্ত্বেও 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 এর মধ্যে হতে হবে। সংকলনের সময় ধ্রুবক সেট করতে ম্যাক্রোও দরকারী।


এটি সম্ভবত সবচেয়ে খারাপ সমাধান (এটি L৪-বিট ধ্রুবকটিতে ইউএলএল প্রত্যয়টিও হারিয়েছে)। এটি সমস্ত ক্ষেত্রে ইনপুট প্রতি 32 টি পরীক্ষা উত্পন্ন করবে। কিছুক্ষণ লুপ ব্যবহার করা ভাল, এটি সর্বদা দ্রুত বা একই গতিতে থাকবে।
xryl669

1
কিন্তু ... ইনপুটটি যদি ধ্রুবক হয় এবং এইভাবে রান সময়ে জিরো অপারেশন হয় তবে এটি প্রিপ্রোসেসর দ্বারা মূল্যায়ন করা যেতে পারে!
মাইকেল

4

সম্পূর্ণতার জন্য এখানে বগ-স্ট্যান্ডার্ড সি-তে একটি ভাসমান-পয়েন্ট বাস্তবায়ন রয়েছে is

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
র্যান্ডম ব্রাউজারগুলি, আপনি এই মন্তব্যটি পড়লে, এই কোডটি চয়ন করুন clearly এটি স্পষ্টভাবে সর্বোত্তম উত্তর, কোনও বিশেষ নির্দেশনা, কোনও বিড়ম্বনা, কেবল দক্ষ, পোর্টেবল এবং মানক কোড। অনুমান করে কেন অন্য কেউ এটিকে
আপত্তি করেনি

5
এলোমেলো ব্রাউজারগুলি, আপনার যদি বিশেষত ভাসমান পয়েন্ট হার্ডওয়্যার না থাকে তবে এটি ধীর গতিতে চলেছে। X86 এ আপনি বিট টুইডলিং ব্যবহার করে এই কোডটির চারপাশে চেনাশোনা চালাতে পারেন। rep bsr ecx,eax; mov eax,0; cmovnz eax,2; shl eax,clপ্রায় 25x দ্রুত।
জোহান

4

পূর্ণসংখ্যার ইনপুটটির জন্য সি / সি ++ তে একটি দক্ষ মাইক্রোসফ্ট (যেমন, ভিজ্যুয়াল স্টুডিও 2017) নির্দিষ্ট সমাধান। সর্বাধিক তাৎপর্যপূর্ণ 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

স্পষ্টতই ভিজ্যুয়াল স্টুডিও সি ++ সংকলকটি সংকলন-সময়ের মানগুলির জন্য এটি অনুকূলিতকরণের জন্য কোড করা হয়নি তবে এটি পুরোপুরি নির্দেশাবলীর মতো নয় not

সম্পাদনা:

আপনি যদি 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));
}

আরও কয়েকটি নির্দেশাবলী উত্পন্ন করে। কৌশলটি হ'ল সূচকটি একটি পরীক্ষা দ্বারা প্রতিস্থাপন করা যেতে পারে তারপরে একটি সেমিওভের নির্দেশনা।


একটি ছোট ভুল: এটি 1 এর জন্য 1 ফিরতে হবে, যদিও এটি হয় না।
0kcats

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

একটি সংস্করণ অন্তর্ভুক্ত করার জন্য উত্তর আপডেট করেছে যা 1 এর ইনপুট মূল্যের জন্য 1 প্রদান করে
নোয়েলসি

3

এক্স 86 এ আপনি এটি দ্রুত করার জন্য 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.wikedia.org/wiki/Find_first_set দেখুন


এটি সর্বোচ্চ সেট বিট (= বিএসআর) সন্ধান বা নেতৃস্থানীয় শূন্যগুলি গণনা করার বিষয়ে নয় not তিনি নিকটতম পাওয়ার 2 অবধি পেতে চান "উত্তর 1 বিয়োগ করে, তারপরে বিএসআর করুন এবং 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 এর নিকটতম নিম্ন শক্তি পাওয়ার চেষ্টা করছি এবং এই ফাংশনটি তৈরি করেছি। এটি আপনাকে সহায়তা করতে পারে J নিকটস্থ 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

@YanDroneaud উত্তরের একটি বৈকল্পিক x==1কেবল x86 প্ল্যাটফর্ম, সংকলক, জিসিসি বা ঝনঝনির জন্য বৈধ :

__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 () ব্যবহার করুন যা সাধারণীকরণের আইইইই প্রতিনিধিত্ব দেখায়।

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

ওপেনজিএল সম্পর্কিত স্টাফগুলির জন্য আপনার যদি এটির প্রয়োজন হয়:

/* 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
'for' একটি লুপ।
ফ্লোরিন

1
ফ্লোরিন: এটা এবং এটি এখানে লুপ হিসাবে ব্যবহৃত হয়, তাই না?
তমাস সিজনে

9
ডাঃ জোকপু - আমার মনে হয় ফ্লোরিন বলতে এখানে বোঝাতে চাইছিলেন যে ওপি একটি লুপ-কম সমাধানের জন্য বলেছিল
এলি বেন্ডারস্কি

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

এটি সি বা সি ++ এ অপরিজ্ঞাত আচরণ এবং ত্রুটির দিকে পরিচালিত করবে। nসিকোয়েন্স পয়েন্ট ব্যতীত একাধিকবার সংশোধন করা অবৈধ। আপনি এটি লিখেছিলেন n-=1যেন প্রথম হওয়া উচিত তবে এখানে কেবলমাত্র গ্যারান্টিটি হ'ল nএতে ;এবং এর প্রথম বন্ধনীর পরে এটির নতুন মান রয়েছে that
সাম হোচেভার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.