আপনার প্রিয় বিট-ওয়াইন কৌশল কী? [বন্ধ]


14

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

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

কয়েক মিনিটের চিন্তার ফলস্বরূপ একটি প্রথম-অর্ডার সমাধান হয়েছে। সমাধানটি শর্তাধীন স্থানান্তরিত হওয়ার আগে নেতিবাচক মানগুলিকে ইতিবাচক মানগুলিতে রূপান্তর করে। একটি মান শর্তসাপেক্ষে শিফট অপারেশন সম্পাদন হওয়ার পরে তার নেতিবাচক আকারে ফিরে আসে।

int a = -5;
int n = 1;

int negative = q < 0; 

a = negative ? -a : a; 
a >>= n; 
a = negative ? -a : a; 

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

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

int a = -5;
int n = 1;

register int sign = (a >> INT_SIZE_MINUS_1) & 1

a = (a - sign) >> n + sign;   

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

উপরের কথাটি বলে আপনি কি উপরের মতো অন্যান্য বিট-ওয়াইজ হ্যাকগুলি ভাবতে পারেন যা এটি আপনার কৌশলগুলির ব্যাগের মধ্যে ফেলেছে? আপনার প্রিয় বিট বুদ্ধিমান হ্যাক কি? আমি সর্বদা নতুন পারফরম্যান্স-ভিত্তিক বিট-ওয়াইজ হ্যাকের সন্ধান করছি।


3
এই প্রশ্ন এবং আপনার অ্যাকাউন্টের নাম -
জে কে

আমার পছন্দ অনুসারে +1 আকর্ষণীয় প্রশ্ন এবং অন্যথায়ও;)
এন্টার

আমি একবারে কিছু দ্রুত সমতা গণনাও করেছি। সমতা কিছুটা ব্যথা হয় কারণ traditionতিহ্যগতভাবে এতে কিছুটা সেট করা থাকলে লুপগুলি এবং গণনা জড়িত। যার সমস্তটিতে প্রচুর জাম্পের প্রয়োজন। শিফট এবং এক্সওআর ব্যবহার করে সমতা গণনা করা যায়, তারপরে একের পর এক সম্পন্ন করা একটি গোছা লুপ এবং জাম্প এড়িয়ে চলে ids
দ্রুত_এখন

2
আপনি কি জানেন যে এই কৌশলগুলি সম্পর্কে একটি পুরো বই আছে? - হ্যাকাররা কল্লোল amazon.com/Hackers-Delight-Henry-S-Warren/dp/0201914654
nikie

হ্যাঁ, একটি ওয়েবসাইট আছে যা বিট ক্রিয়াকলাপগুলিতেও নিবেদিত। আমি ইউআরএল ভুলে গেছি তবে গুগল এটি খুব শীঘ্রই চালু করবে।
দ্রুত_ এখন

উত্তর:


23

আমি গসপার্সের হ্যাক (হাক্মেম # 175) পছন্দ করি, একটি নম্বর নেওয়া এবং একই সংখ্যক বিটের সেট সহ পরবর্তী নম্বর পাওয়ার একটি খুব চালাকি উপায়। উদাহরণস্বরূপ, এইভাবে kআইটেমগুলির সংমিশ্রণে এটি দরকারী n:

int set = (1 << k) - 1;
int limit = (1 << n);
while (set < limit) {
    doStuff(set);

    // Gosper's hack:
    int c = set & -set;
    int r = set + c;
    set = (((r^set) >>> 2) / c) | r;
}

7
+1 টি। তবে এখন থেকে, কোনও মন্তব্য ছাড়াই ডিবাগিং সেশনের সময় এটির সন্ধানের জন্য আমার দুঃস্বপ্ন হবে ।
নিকি

@ নিকি, মুয়াহাহাহাহাহা! (আমি প্রকল্প ইউলারের সমস্যাগুলির মতো জিনিসের জন্য এটি ব্যবহার করার ঝোঁক রাখি - আমার দিনের চাকরিতে খুব বেশি সংযুক্তি জড়িত না)।
পিটার টেলর

7

ফাস্ট বিপরীত বর্গ রুট পদ্ধতি একটি বর্গমূল বিপরীত যে আমার দেখা কম্পিউটিং সবচেয়ে উদ্ভট বিট-স্তর কৌশল ব্যবহার করে:

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking [sic]
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck? [sic]
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
    //    y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}

দ্রুত স্কয়ারটিও আশ্চর্যজনক। কারম্যাক মনে হয় একটি দুর্দান্ত কোডার।
বেনজামিনবি

উইকিপিডিয়ায় আরও পুরানো উত্স রয়েছে, যেমন: 3d.com/content/articles/15
এমসাল্টার্স

0

3 দ্বারা ভাগ করুন - একটি রান-টাইম লাইব্রেরি কলটি অবলম্বন না করে।

দেখা যাচ্ছে যে 3 দ্বারা বিভাজন (স্ট্যাক ওভারফ্লোতে একটি ইঙ্গিতকে ধন্যবাদ) এরূপ হিসাবে প্রায় করা যেতে পারে:

এক্স / 3 = [(x / 4) + (x / 12)]

এবং এক্স / 12 হ'ল (এক্স / 4) / 3. হঠাৎ এখানে পুনরাবৃত্তির একটি উপাদান উপস্থিত রয়েছে।

এটি এছাড়াও সক্রিয় যে আপনি যে সংখ্যাগুলিতে খেলছেন তার সীমাটি যদি সীমাবদ্ধ করে রাখেন তবে আপনি প্রয়োজনীয় পুনরাবৃত্তির সংখ্যা সীমাবদ্ধ করতে পারেন।

এবং এইভাবে, স্বাক্ষরবিহীন পূর্ণসংখ্যার জন্য <2000, নিম্নলিখিতটি একটি দ্রুত এবং সাধারণ / 3 অ্যালগরিদম। (বড় সংখ্যার জন্য, আরও পদক্ষেপ যুক্ত করুন)। সংকলকগণ হ্যাকটিকে এর বাইরে নিয়ে আসে তাই এটি দ্রুত এবং ছোট হয়ে যায়:

স্ট্যাটিক স্বাক্ষরযুক্ত শর্ট ফাস্টডাইভাইড 3 (কনস্টাইন স্বাক্ষরযুক্ত স্বল্প আর্গ)
{
  স্বাক্ষরযুক্ত স্বল্প রানিংসাম;
  স্বাক্ষরযুক্ত স্বল্প ফ্র্যাকশনাল টুথথ;

  রানিংসাম = আরগ >> 2;

  ফ্র্যাকশনালওয়েলথ = রানিংসাম >> 2;
  রানিংসাম + = ফ্র্যাকশনাল টুথথ;

  ফ্র্যাকশনাল টোথথ >> = 2;
  রানিংসাম + = ফ্র্যাকশনাল টুথথ;

  ফ্র্যাকশনাল টোথথ >> = 2;
  রানিংসাম + = ফ্র্যাকশনাল টুথথ;

  ফ্র্যাকশনাল টোথথ >> = 2;
  রানিংসাম + = ফ্র্যাকশনাল টুথথ;

  // আরও নির্ভুলতার জন্য উপরের 2 লাইনের আরও পুনরাবৃত্তি

  ফিরে রানিংসাম;
}

1
অবশ্যই এটি খুব অস্পষ্ট মাইক্রোকন্ট্রোলারদের ক্ষেত্রেই প্রাসঙ্গিক। গত দুই দশকে তৈরি কোনও আসল সিপিইউয়ের পূর্ণসংখ্যা বিভাগের জন্য রান-টাইম লাইব্রেরির প্রয়োজন নেই।
এমসাল্টারস

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

ভাল, নোংরা ... এটি কেবলমাত্র দ্বারা .0101010101গুণমান (প্রায় ১/৩)। প্রো টিপ: আপনিও দ্বারা গুন করতে পারেন .000100010001এবং 101(যা মাত্র 3 বিটশিফ্ট নেয়, তবুও আরও ভাল অনুমান করা যায়.010101010101
এমএসাল্টারস

আমি কেবলমাত্র পূর্ণসংখ্যা এবং কোনও ভাসমান বিন্দু দিয়ে কীভাবে এটি করতে পারি?
দ্রুত_ এখন

1
বিটওয়াইজ, এক্স * 101 = এক্স + এক্স << ২. একইভাবে, x * 0.000100010001 হল x >> 4 + এক্স >> 8 + এক্স >> 12
এমসাল্টার্স

0

যদি আপনি এরলংয়ের দিকে লক্ষ্য করেন তবে বিট অপারেশন করার জন্য একটি সম্পূর্ণ ডিএসএল রয়েছে। সুতরাং আপনি এই জাতীয় কিছু বলে বিট দিয়ে একটি ডেটাস্ট্রাকচার ভেঙে ফেলতে পারেন:

<> = << 1,17,42: 16 >>।

এখানে সম্পূর্ণ বিবরণ: http://www.erlang.org/doc/references_manual/expressions.html#id75782

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