সি / সি ++ এ বাইটে বিটের ক্রমটি বিপরীত করার সহজ উপায় কী?


110

বাইটে বিট অর্ডার বিপরীত করার একাধিক উপায় রয়েছে, তবে বিকাশকারী বাস্তবায়নের জন্য "সরলতম" কী তা সম্পর্কে আমি আগ্রহী। এবং বিপরীত দ্বারা আমি বলতে চাই:

1110 -> 0111
0010 -> 0100

এটি অনুরূপ, তবে এই পিএইচপি প্রশ্নের সদৃশ নয় ।

এটি অনুরূপ, তবে এই সি প্রশ্নের সদৃশ নয় । এই প্রশ্নটি কোনও বিকাশকারী দ্বারা কার্যকর করার সবচেয়ে সহজ পদ্ধতির জন্য জিজ্ঞাসা করছে। "সেরা অ্যালগরিদম" স্মৃতি এবং সিপিইউ অভিনয় নিয়ে উদ্বিগ্ন।


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

@ আন্ড্রেয়াস সরল বাস্তবায়ন
নাথান

উত্তর:


102

যদি আপনি একটি একক বাইট সম্পর্কে কথা বলছেন তবে কোনও টেবিল-অনুসন্ধান সম্ভবত সেরা বেট, যদি কোনও কারণে আপনার 256 বাইট না থাকে।


12
আমরা যদি এমন কোনও প্রস্তুতির সমাধানটি অনুলিপি না করে কার্যকর করার জন্য সহজ কিছু সম্পর্কে কথা বলি, তবে সন্ধানের টেবিল তৈরি করার জন্য আরও একটি সমাধান প্রয়োজন। (অবশ্যই এটি হাতে হাতে করা সম্ভব, তবে এটি ত্রুটি-প্রবণ এবং সময়সাপেক্ষ ...)
আরক্কু

7
আপনি যদি প্যালিনড্রোমগুলিকে অগ্রাহ্য করেন তবে আপনি অ্যারেটিকে 256 বাইটের থেকে কিছুটা কম কমে যেতে পারেন।
উইলহেমটেল

8
@ উইলহেলমটেল - প্যালিনড্রোমগুলি কোনটি তা জানতে আপনার একটি টেবিলের প্রয়োজন হবে।
মার্ক রান্সম

6
@ উইলহেমটেল: ঠিক আছে, স্ক্রিপ্টটি লেখার জন্য এখনও আরেকটি সমাধান প্রয়োজন, যা আমার বক্তব্য ছিল - একটি দেখার টেবিলটি ব্যবহার করা সহজ তবে তৈরি করা সহজ নয়। (রেডিমেড লুকিং টেবিলটি অনুলিপি ব্যতীত তবে কোনওটি সমাধানের অনুলিপি করতে পারে)) উদাহরণস্বরূপ, যদি "সাদামাটা" সমাধানটি পরীক্ষায় বা সাক্ষাত্কারে কাগজে লেখা যেতে পারে এমন বিবেচনা করা হয়, তবে আমি তা করব না হাত দিয়ে একটি অনুসন্ধানের টেবিল তৈরি করা এবং এটি করার জন্য প্রোগ্রামটি তৈরি করা ইতিমধ্যে একটি আলাদা সমাধান অন্তর্ভুক্ত করবে (যা এটি এবং টেবিল উভয়ই সহকারে একা সহজ হবে)।
আরক্কু

4
@ আরক্কু বলতে যা বোঝাতে চেয়েছি তা হ'ল একটি স্ক্রিপ্ট লিখুন যা প্রথম 256 বাইটের টেবিল এবং তাদের বিপরীত ম্যাপিংয়ের ফলাফল দেয়। হ্যাঁ, আপনি বিপরীত ফাংশনটি লিখতে ফিরে এসেছেন, তবে এখন আপনার পছন্দের স্ক্রিপ্টিং ভাষায় এবং এটি আপনার পছন্দ মতোই বাজে হতে পারে - আপনি এটি শেষ হওয়ার সাথে সাথে তা ফেলে দিতে চলেছেন এবং আপনি একবার এটি চালিয়েছিলেন। সি কোড হিসেবে স্ক্রিপ্টের আউটপুট, এমনকি আছে: unsigned int rtable[] = {0x800, 0x4000, ...};। তারপরে স্ক্রিপ্টটি ফেলে দিন এবং ভুলে যান যে আপনার এটি কখনও ছিল। সমতুল্য সি ++ কোডের তুলনায় এটি লিখতে অনেক দ্রুত এবং এটি কেবল একবারই চলবে, সুতরাং আপনি আপনার সি ++ কোডে ও (1) রানটাইম পাবেন।
উইলহেমটেল

227

এই কাজ করা উচিত:

unsigned char reverse(unsigned char b) {
   b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
   b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
   b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
   return b;
}

প্রথমে বাম চারটি বিট ডান চার বিট দিয়ে অদলবদল করা হয়। তারপরে সমস্ত সংলগ্ন জোড়াটি অদলবদল করা হয় এবং তারপরে সমস্ত সংলগ্ন একক বিট। এটি একটি বিপরীত ক্রমে ফলাফল।


26
যুক্তিসঙ্গতভাবে সংক্ষিপ্ত এবং দ্রুত, তবে সহজ নয়।
মার্ক র্যানসম

3
এই পদ্ধতির পরিচ্ছন্নতার সাথে বায়ান অদলবদল করার জন্য পরিষ্কারভাবে জেনারেলাইজ করে।
বুজুম

2
সহজ পদ্ধতির নয়, তবে আমি এটি পছন্দ করি +1।
নাথান

7
হ্যাঁ, এটা সহজ। এটি এক ধরণের বিভাজন এবং বিজয়ী অ্যালগরিদম। অসাধারণ!
কিউইক

নীচে @ আরক্কু প্রস্তাবিত পদ্ধতির চেয়েও কি দ্রুত?
কিড

122

আমি মনে করি একটি সন্ধানের টেবিলটি সহজতম পদ্ধতিগুলির মধ্যে একটি হতে হবে। যাইহোক, আপনার একটি সম্পূর্ণ সারণীর দরকার নেই।

//Index 1==0b0001 => 0b1000
//Index 7==0b0111 => 0b1110
//etc
static unsigned char lookup[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };

uint8_t reverse(uint8_t n) {
   // Reverse the top and bottom nibble then swap them.
   return (lookup[n&0b1111] << 4) | lookup[n>>4];
}

// Detailed breakdown of the math
//  + lookup reverse of bottom nibble
//  |       + grab bottom nibble
//  |       |        + move bottom result into top nibble
//  |       |        |     + combine the bottom and top results 
//  |       |        |     | + lookup reverse of top nibble
//  |       |        |     | |       + grab top nibble
//  V       V        V     V V       V
// (lookup[n&0b1111] << 4) | lookup[n>>4]

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


10
এটি টেবিল সমাধানের জটিলতা হ্রাস করার একটি দুর্দান্ত উপায়। +1
জেমস

3
দুর্দান্ত, তবে আপনাকে একটি ক্যাশে মিস দেবে।
জোহান কোটলিনস্কি

7
@ কোটলিনস্কি: কী ক্যাশে মিস করবেন? আমি মনে করি ছোট টেবিল সংস্করণটি বড়টির চেয়ে বেশি ক্যাশে দক্ষ হতে পারে। আমার Core2 এ একটি ক্যাশে লাইন by৪ বাইট প্রশস্ত, পূর্ণ টেবিলটি একাধিক লাইন বিস্তৃত করবে, অন্যদিকে ছোট টেবিলটি সহজেই একটি এক লাইনের সাথে ফিট করে।
ডিফ্ট_কোড

4
@kotlinski: টেম্পোরাল স্থান, ক্যাশে হিট বা প্রতিস্থাপন কৌশল জন্য আরো গুরুত্বপূর্ণ তুলনায় ঠিকানা এলাকায়
cfi

6
@ হর্ষদীপ: টেবিল এন্ট্রিগুলির বাইনারি এনকোডড সূচকগুলি বিবেচনা করুন। সূচী b0000 (0) -> b0000 (0x0) বোরিং; b0001(1) -> b1000(0x8), b0010(2) -> b0100(0x4), b1010(10) -> b0101(0x5)। প্যাটার্নটি দেখুন? এটি যথেষ্ট সহজ যে আপনি এটি আপনার মাথায় গণনা করতে পারেন (আপনি যদি বাইনারি পড়তে পারেন, অন্যথায় এটি কার্যকর করার জন্য আপনার কাগজের প্রয়োজন হবে)। লিপ হিসাবে যে একটি 8 বিট পূর্ণসংখ্যার বিপরীত 4 বিট অংশ বিপরীত তারপর সেগুলি অদলবদল হিসাবে সমান; আমি অভিজ্ঞতা এবং অন্তর্দৃষ্টি (বা যাদু) দাবি করি।
ডিফ্ট_কোড

46

অনেকগুলি সমাধানের জন্য বিট টুইডলিং হ্যাকগুলি দেখুন । সেখান থেকে কপিপাস্টিং বাস্তবায়নের পক্ষে স্পষ্টতই সহজ। =)

উদাহরণস্বরূপ (32-বিট সিপিইউতে):

uint8_t b = byte_to_reverse;
b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;

যদি "বাস্তবায়নের পক্ষে সহজ" এর অর্থ যদি এমন কিছু হয় যা পরীক্ষা বা কাজের সাক্ষাত্কারে কোনও রেফারেন্স ছাড়াই করা যায়, তবে নিরাপদ বেট সম্ভবত বিটগুলির একের পর এক বিপরীতে ক্রিয়াকলাপের অনর্থক অনুলিপি করা (ইতিমধ্যে অন্যান্য উত্তরে দেখানো হয়েছে) )।


1
আপনার ইউআরএল থেকে: 32 বিট সিপিইউ: বি = ((বি * 0x0802LU & 0x22110LU) | (খ * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
জোশুয়া

1
@ জোশুয়া: এটি আমার ব্যক্তিগত প্রিয়ও। সাবধানতা (লিঙ্কযুক্ত পৃষ্ঠায় বর্ণিত) হ'ল এটি নির্ধারিত বা একটি uint8_t এ নিক্ষেপ করা প্রয়োজন বা উপরের বিটগুলিতে আবর্জনা থাকবে।
আরক্কু

41

যেহেতু কেউই সম্পূর্ণ টেবিল দেখার সমাধান পোস্ট করেনি, তাই এখানে আমার:

unsigned char reverse_byte(unsigned char x)
{
    static const unsigned char table[] = {
        0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
        0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
        0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
        0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
        0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
        0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
        0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
        0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
        0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
        0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
        0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
        0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
        0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
        0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
        0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
        0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
        0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
        0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
        0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
        0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
        0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
        0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
        0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
        0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
        0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
        0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
        0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
        0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
        0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
        0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
        0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
        0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
    };
    return table[x];
}

2
দরকারী, ধন্যবাদ। দেখে মনে হচ্ছে যে আমার ধীর স্থানান্তর পদ্ধতিটি একটি এম্বেড থাকা অ্যাপ্লিকেশনটিতে পারফরম্যান্সকে সীমাবদ্ধ করে চলেছে। একটি পিআইসিতে রমে টেবিল স্থাপন করা হয়েছে (রম কীওয়ার্ড সংযোজন সহ)।
ফ্লাইট করুন


25
template <typename T>
T reverse(T n, size_t b = sizeof(T) * CHAR_BIT)
{
    assert(b <= std::numeric_limits<T>::digits);

    T rv = 0;

    for (size_t i = 0; i < b; ++i, n >>= 1) {
        rv = (rv << 1) | (n & 0x01);
    }

    return rv;
}

সম্পাদনা করুন:

Itচ্ছিক বিটকাউন্টের সাহায্যে এটিকে কোনও টেম্পলেটে রূপান্তরিত করা হয়েছে


@ এনভিএল - স্থির আমি এটি একটি টেমপ্লেট হিসাবে তৈরি করতে শুরু করেছিলাম তবে অর্ধেকটা না করে সিদ্ধান্ত নিয়েছি ... অনেক বেশি &
জিটি

অতিরিক্ত pedenatry জন্য প্রতিস্থাপন sizeof(T)*8সঙ্গে sizeof(T)*CHAR_BITS
পিলসি

6
@andand অতিরিক্ত অতিরিক্ত pendantry জন্য প্রতিস্থাপন sizeof(T)*CHAR_BITদ্বারা std::numeric_limits<T>::digits(প্রায় 4 পরে পণ্ডিতিপনা বছর)।
মরউভেন

1
এটা হওয়া উচিত CHAR_BIT, না CHAR_BITS
জুনি

1
এটি হওয়া উচিত rv = (আরভি << 1) | (এন & 0x01);
বিগনেশ

16

দুটি লাইন:

for(i=0;i<8;i++)
     reversed |= ((original>>i) & 0b1)<<(7-i);

বা আপনার "0 বি 1" অংশটি নিয়ে সমস্যা রয়েছে:

for(i=0;i<8;i++)
     reversed |= ((original>>i) & 1)<<(7-i);

"আসল" হ'ল বাইটটি আপনি বিপরীত করতে চান। "বিপরীত" ফলাফল, 0 এ আরম্ভ করা হয়।


14

যদিও সম্ভবত বহনযোগ্য নয়, আমি সমাবেশ ভাষা ব্যবহার করব।
অনেক অ্যাসেম্বলি ভাষায় ক্যারি পতাকাটিতে কিছুটা ঘোরানো এবং কেরি পতাকাটি শব্দের (বা বাইট) মধ্যে ঘোরানোর জন্য নির্দেশনা রয়েছে।

অ্যালগরিদমটি হ'ল:

for each bit in the data type:
  rotate bit into carry flag
  rotate carry flag into destination.
end-for

এর জন্য উচ্চ স্তরের ভাষার কোডটি আরও জটিল, কারণ সি এবং সি ++ বহন করতে ঘুরতে এবং বাহন থেকে ঘোরানো সমর্থন করে না। ক্যারি পতাকা মডেলিং করতে হবে।

সম্পাদনা করুন: উদাহরণস্বরূপ সমাবেশের ভাষা language

;  Enter with value to reverse in R0.
;  Assume 8 bits per byte and byte is the native processor type.
   LODI, R2  8       ; Set up the bit counter
Loop:
   RRC, R0           ; Rotate R0 right into the carry bit.
   RLC, R1           ; Rotate R1 left, then append carry bit.
   DJNZ, R2  Loop    ; Decrement R2 and jump if non-zero to "loop"
   LODR, R0  R1      ; Move result into R0.

7
আমি মনে করি এই উত্তরটি সাধারণের বিপরীত। অ-বহনযোগ্য, সমাবেশ এবং প্রকৃত সমাবেশের পরিবর্তে সিউডো কোডে যথেষ্ট লিখিত জটিল।
deft_code

3
এটা বেশ সহজ। আমি এটি ছদ্ম-কোডে রেখেছি কারণ সমাবেশে স্মৃতিবিদ্যাগুলি প্রসেসরের একটি জাতের জন্য নির্দিষ্ট এবং সেখানে প্রচুর জাত রয়েছে are আপনি যদি চান তবে সাধারণ সমাবেশ ভাষা দেখানোর জন্য আমি এটি সম্পাদনা করতে পারি।
টমাস ম্যাথিউজ

একটি কম্পাইলার অপ্টিমাইজেশন উপযুক্ত সমাবেশ নির্দেশের মধ্যে সহজতর হয় কিনা তা দেখতে পেল could
স্পার্কি

12

আমি এখানে অন্যান্য বিট মজাদার অ্যালগরিদমগুলির চেয়ে সহজ সমাধানটি পেয়েছি।

unsigned char reverse_byte(char a)
{

  return ((a & 0x1)  << 7) | ((a & 0x2)  << 5) |
         ((a & 0x4)  << 3) | ((a & 0x8)  << 1) |
         ((a & 0x10) >> 1) | ((a & 0x20) >> 3) |
         ((a & 0x40) >> 5) | ((a & 0x80) >> 7);
}

এটি বাইটে প্রতিটি বিট পায় এবং প্রথম থেকে শেষ পর্যন্ত শুরু করে এটি অনুসারে স্থানান্তর করে।

ব্যাখ্যা:

   ((a & 0x1) << 7) //get first bit on the right and shift it into the first left position 
 | ((a & 0x2) << 5) //add it to the second bit and shift it into the second left position
  //and so on

সুন্দর! আমার প্রিয় এখন পর্যন্ত।
নিক রামাউ

এটি অবশ্যই সহজ, তবে এটি চিহ্নিত করা উচিত যে কার্যকর করার সময়টি ও (লগ এন) এর চেয়ে ও (এন) হয়, যেখানে এন বিটের সংখ্যা (8, 16, 32, 64, ইত্যাদি)।
টড লেহম্যান

10

সবচেয়ে সহজ উপায় লুপ বিট অবস্থানের পুনরুক্তি সম্ভবত হল:

unsigned char reverse(unsigned char c) {
   int shift;
   unsigned char result = 0;
   for (shift = 0; shift < CHAR_BIT; shift++) {
      if (c & (0x01 << shift))
         result |= (0x80 >> shift);
   }
   return result;
}

এটি CHAR_BIT, কোনও 's' ছাড়াই
ljrk

CHAR_BITআপনি যখন char8 টি বিট অনুমান করবেন তখন কেন ব্যবহার করবেন ?
chqrlie

6

ধ্রুবক, 8-বিট ইনপুটের খুব সীমিত ক্ষেত্রে , এই পদ্ধতিটিতে রান-টাইমে কোনও মেমরি বা সিপিইউ খরচ হয় না:

#define MSB2LSB(b) (((b)&1?128:0)|((b)&2?64:0)|((b)&4?32:0)|((b)&8?16:0)|((b)&16?8:0)|((b)&32?4:0)|((b)&64?2:0)|((b)&128?1:0))

আমি এটি এআরআইএনসি -২২৯ এর জন্য ব্যবহার করেছি যেখানে লেবেলের বিট ক্রম (শেষের দিক) বাকী শব্দের বিপরীতে রয়েছে। লেবেলটি প্রায়শই একটি ধ্রুবক এবং প্রচলিতভাবে অষ্টালে থাকে।

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

#define LABEL_HF_COMM MSB2LSB(0205)

আরও উদাহরণ:

assert(0b00000000 == MSB2LSB(0b00000000));
assert(0b10000000 == MSB2LSB(0b00000001));
assert(0b11000000 == MSB2LSB(0b00000011));
assert(0b11100000 == MSB2LSB(0b00000111));
assert(0b11110000 == MSB2LSB(0b00001111));
assert(0b11111000 == MSB2LSB(0b00011111));
assert(0b11111100 == MSB2LSB(0b00111111));
assert(0b11111110 == MSB2LSB(0b01111111));
assert(0b11111111 == MSB2LSB(0b11111111));
assert(0b10101010 == MSB2LSB(0b01010101));

5

আপনার আগ্রহ থাকতে পারে std::vector<bool>(এটি বিট-প্যাকড) এবংstd::bitset

অনুরোধ অনুসারে এটি সহজতম হওয়া উচিত।

#include <iostream>
#include <bitset>
using namespace std;
int main() {
  bitset<8> bs = 5;
  bitset<8> rev;
  for(int ii=0; ii!= bs.size(); ++ii)
    rev[bs.size()-ii-1] = bs[ii];
  cerr << bs << " " << rev << endl;
}

অন্যান্য বিকল্পগুলি দ্রুত হতে পারে।

সম্পাদনা: আমি আপনার ব্যবহার করে একটি সমাধান .ণী std::vector<bool>

#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
using namespace std;
int main() {
  vector<bool> b{0,0,0,0,0,1,0,1};
  reverse(b.begin(), b.end());
  copy(b.begin(), b.end(), ostream_iterator<int>(cerr));
  cerr << endl;
}

দ্বিতীয় উদাহরণটির জন্য সি ++ 0 এক্স এক্সটেনশান প্রয়োজন (এর সাথে অ্যারে শুরু করতে {...})। একটি bitsetবা একটি std::vector<bool>(বা ক boost::dynamic_bitset) ব্যবহারের সুবিধাটি হ'ল আপনি বাইট বা শব্দের মধ্যে সীমাবদ্ধ নন তবে বিটগুলির একটি নির্বিচার সংখ্যাকে বিপরীত করতে পারেন।

আছে HTH


এখানে কোনও পোডের চেয়ে বিটসেট কী সহজ? কোডটি দেখান, না হয় না।
উইলহেমটেল

আসলে, আমি মনে করি যে কোডটি বিটসেটকে বিপরীত করবে এবং তারপরে আবার এটির আসল দিকে ফিরিয়ে দেবে। Ii! = আকার () পরিবর্তন করুন ; থেকে ii <আকার () / 2; এবং এটি আরও ভাল কাজ করবে =)
ভিক্টর সেহর

(@ ভিক্টর-সেহর নং, এটি হবে না, রেভ বিএস থেকে আলাদা)। যাইহোক আমি নিজের উত্তরটি পছন্দ করি না: আমি মনে করি এটি এমন একটি ক্ষেত্রে যেখানে বাইনারি পাটিগণিত এবং শিফ্ট অপারেটররা আরও উপযুক্ত। এটি এখনও বুঝতে সহজ সরল।
বাওল

কীভাবে std::vector<bool> b = { ... }; std::vector<bool> rb ( b.rbegin(), b.rend()); - সরাসরি বিপরীত পুনরুক্তি ব্যবহার করে?
এমসাল্টার 21

@ এসএমএলটাররা আমি এর অপরিবর্তনীয়তা পছন্দ করি।
বাওল

5

আপনি "সরলতম উপায়" বলতে কী বোঝায় তার উপর নির্ভর করে বিটগুলি বিপরীত করার অনেকগুলি উপায় রয়েছে।


ঘূর্ণন দ্বারা বিপরীত

সম্ভবত সবচেয়ে যুক্তিসঙ্গত, প্রথমটিতে একটি মাস্ক প্রয়োগ করার সময় বাইটটি ঘোরানোর মধ্যে থাকে (n & 1):

unsigned char reverse_bits(unsigned char b)
{
    unsigned char   r = 0;
    unsigned        byte_len = 8;

    while (byte_len--) {
        r = (r << 1) | (b & 1);
        b >>= 1;
    }
    return r;
}

1) একটি স্বাক্ষরকারী চরটির দৈর্ঘ্য 1 বাইট হিসাবে, যা 8 বিটের সমান, এর অর্থ আমরা প্রতিটি বিট স্ক্যান করব while (byte_len--)

2) আমরা প্রথমে খ পরীক্ষা করে দেখি যে খ হিসাবে ডানদিকে চূড়ান্ত কিছুটা (b & 1); যদি তাই হয় তবে আমরা আর এর সাথে বিট 1 সেট করেছি |এবং এটি 2 দিয়ে আর দিয়ে গুণকে 1 বামে রেখেছি(r << 1)

3) তারপরে আমরা b >>=1ভেরিয়েবলের চূড়ান্ত ডানদিকে অবস্থিত বিটটি মুছতে আমাদের স্বাক্ষরযুক্ত চর বিটিকে 2 দিয়ে বিভক্ত করি । অনুস্মারক হিসাবে, খ >> = 1; খ / = 2 এর সমতুল্য;


এক লাইনে বিপরীত

এই সমাধানটি প্রোগ্রামিং হ্যাকস বিভাগে রিচ শ্রোপেলকে দায়ী করা হয়

unsigned char reverse_bits3(unsigned char b)
{
    return (b * 0x0202020202ULL & 0x010884422010ULL) % 0x3ff;
}

1) গুণমান অপারেশন (খ * 0x0202020202ULL) একটি 64৪-বিট মানটিতে ফ্যান-আউট করার জন্য 8-বিট বাইট প্যাটার্নের পাঁচটি পৃথক অনুলিপি তৈরি করে।

2) অ্যান্ড অপারেশন (& 0x010884422010ULL) বিটগুলির প্রতিটি 10-বিট গ্রুপের তুলনায় সঠিক (বিপরীত) পজিশনে থাকা বিটগুলি নির্বাচন করে।

3) একসাথে গুণ এবং এ্যান্ড অপারেশনগুলি মূল বাইট থেকে বিটগুলি অনুলিপি করে যাতে তারা প্রত্যেকে কেবল 10-বিট সেটের মধ্যে একটিতে উপস্থিত হয়। মূল বাইট থেকে বিটের বিপরীত অবস্থানগুলি যে কোনও 10-বিট সেটের মধ্যে তাদের সম্পর্কিত অবস্থানের সাথে মিলে যায়।

4) শেষ পদক্ষেপ (% 0x3 এফ), যার মধ্যে 2 ^ 10 - 1 দ্বারা মডুলাস বিভাজন জড়িত - 1 এর বিটগুলির প্রতিটি সেট একসাথে একত্রিত করার প্রভাব রয়েছে (0-9, 10-19, 20-29 পজিশন থেকে ...) 64-বিট মান। এগুলি ওভারল্যাপ হয় না, সুতরাং মডিউলাস বিভাগের অন্তর্গত অতিরিক্ত পদক্ষেপগুলি ওআর অপারেশনগুলির মতো আচরণ করে।


বিভাজন এবং সমাধান সমাধান

unsigned char reverse(unsigned char b) {
   b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
   b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
   b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
   return b;
}

এটি সর্বাধিক উর্ধ্বমুখী উত্তর এবং কিছু ব্যাখ্যা থাকা সত্ত্বেও, আমি মনে করি যে বেশিরভাগ মানুষের কাছে 0xF0, 0xCC, 0xAA, 0x0F, 0x33 এবং 0x55 এর সত্যিকারের অর্থ কী তা কল্পনা করতে অসুবিধা বোধ হয়।

এটি '0 বি' এর সুবিধা নেবে না যা একটি জিসিসি এক্সটেনশন এবং এটি সি ++ 14 স্ট্যান্ডার্ডের পরে অন্তর্ভুক্ত, ডিসেম্বর 2014 এ প্রকাশিত হয়েছে, সুতরাং এপ্রিল 2010 থেকে ডেটিংয়ের এই উত্তরটির কিছুক্ষণ পরে

'0' এবং '1' ডিজিটের অনুক্রম, '0 বি' বা '0 বি' দ্বারা উপস্থাপিত, বাইনারি ধ্রুবক হিসাবে পূর্ণসংখ্যার ধ্রুবককে রচনা করা যেতে পারে। এটি বিভাজন স্তরে (মাইক্রোকন্ট্রোলারদের মতো) প্রচুর পরিমাণে চালিত পরিবেশে বিশেষত কার্যকর।

আমরা যেখানে অর্ধে অর্ধেক স্থানান্তর করি সেখানে এই সমাধানটি আরও ভালভাবে মনে রাখতে এবং বুঝতে দয়া করে কোড স্নিপেটগুলি নীচে দেখুন:

unsigned char reverse(unsigned char b) {
   b = (b & 0b11110000) >> 4 | (b & 0b00001111) << 4;
   b = (b & 0b11001100) >> 2 | (b & 0b00110011) << 2;
   b = (b & 0b10101010) >> 1 | (b & 0b01010101) << 1;
   return b;
}

নোট: >> 4এটি কারণ হ'ল 1 বাইটে 8 টি বিট রয়েছে যা স্বাক্ষরবিহীন চর তাই আমরা অন্য অর্ধেক নিতে চাই, ইত্যাদি।

আমরা সহজেই কেবল দুটি অতিরিক্ত লাইন এবং একই যুক্তি অনুসরণ করে 4 বাইটে এই সমাধানটি প্রয়োগ করতে পারি। যেহেতু উভয় মুখোশ একে অপরের পরিপূরক হয় আমরা এমনকি ব্যবহার করতে পারি b বিটগুলি পরিবর্তন করতে এবং কিছু কালি সংরক্ষণ করতে:

uint32_t reverse_integer_bits(uint32_t b) {
   uint32_t mask = 0b11111111111111110000000000000000;
   b = (b & mask) >> 16 | (b & ~mask) << 16;
   mask = 0b11111111000000001111111100000000;
   b = (b & mask) >> 8 | (b & ~mask) << 8;
   mask = 0b11110000111100001111000011110000;
   b = (b & mask) >> 4 | (b & ~mask) << 4;
   mask = 0b11001100110011001100110011001100;
   b = (b & mask) >> 2 | (b & ~mask) << 2;
   mask = 0b10101010101010101010101010101010;
   b = (b & mask) >> 1 | (b & ~mask) << 1;
   return b;
}

[সি ++ কেবল] বিহীন যেকোন স্বাক্ষরিত (টেম্পলেট)

উপরোক্ত যুক্তিটি এমন একটি লুপের সাথে সংক্ষিপ্ত করা যায় যা স্বাক্ষরবিহীন যে কোনও ধরণের ক্ষেত্রে কাজ করবে:

template <class T>
T reverse_bits(T n) {
    short bits = sizeof(n) * 8; 
    T mask = ~T(0); // equivalent to uint32_t mask = 0b11111111111111111111111111111111;

    while (bits >>= 1) {
        mask ^= mask << (bits); // will convert mask to 0b00000000000000001111111111111111;
        n = (n & ~mask) >> bits | (n & mask) << bits; // divide and conquer
    }

    return n;
}

উপরের ফাংশনটি অন্তর্ভুক্ত করে নিজে চেষ্টা করুন:

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

template <class T>
void print_binary(T n)
{   T mask = 1ULL << ((sizeof(n) * 8) - 1);  // will set the most significant bit
    for(; mask != 0; mask >>= 1) putchar('0' | !!(n & mask));
    putchar('\n');
}

int main() {
    uint32_t n = 12;
    print_binary(n);
    n = reverse_bits(n); 
    print_binary(n);
    unsigned char c = 'a';
    print_binary(c);
    c = reverse_bits(c);
    print_binary(c);
    uint16_t s = 12;
    print_binary(s);
    s = reverse_bits(s);
    print_binary(s);
    uint64_t l = 12;
    print_binary(l);
    l = reverse_bits(l);
    print_binary(l);
    return 0;
}

Asm উদ্বায়ী সঙ্গে বিপরীত

সর্বশেষে তবে সর্বনিম্ন নয়, যদি সহজতমটির অর্থ কম লাইন হয় তবে কেন সমাবেশকে ইনলাইন করার চেষ্টা করবেন না?

-masm=intelসংকলন করার সময় আপনি কোড স্নিপেটের নীচে পরীক্ষা করতে পারেন :

unsigned char reverse_bits(unsigned char c) {
    __asm__ __volatile__ (R"(
        mov cx, 8       
    daloop:                   
        ror di          
        adc ax, ax      
        dec cx          
        jnz short daloop  
    ;)");
}

লাইন দ্বারা ব্যাখ্যা লাইন:

        mov cx, 8       ; we will reverse the 8 bits contained in one byte
    daloop:             ; while loop
        shr di          ; Shift Register `di` (containing value of the first argument of callee function) to the Right
        rcl ax          ; Rotate Carry Left: rotate ax left and add the carry from shr di, the carry is equal to 1 if one bit was "lost" from previous operation 
        dec cl          ; Decrement cx
        jnz short daloop; Jump if cx register is Not equal to Zero, else end loop and return value contained in ax register

3

সারণী অনুসন্ধান বা

uint8_t rev_byte(uint8_t x) {
    uint8_t y;
    uint8_t m = 1;
    while (m) {
       y >>= 1;
       if (m&x) {
          y |= 0x80;
       }
       m <<=1;
    }
    return y;
}

সম্পাদন করা

আপনার জন্য আরও ভাল কাজ করতে পারে এমন অন্যান্য সমাধানের জন্য এখানে দেখুন


3

একটি ধীর কিন্তু সহজ বাস্তবায়ন:

static int swap_bit(unsigned char unit)
{
    /*
     * swap bit[7] and bit[0]
     */
    unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01)) << 7) | (unit & 0x7f));
    unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01))) | (unit & 0xfe));
    unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01)) << 7) | (unit & 0x7f));

    /*
     * swap bit[6] and bit[1]
     */
    unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02)) << 5) | (unit & 0xbf));
    unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02))) | (unit & 0xfd));
    unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02)) << 5) | (unit & 0xbf));

    /*
     * swap bit[5] and bit[2]
     */
    unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04)) << 3) | (unit & 0xdf));
    unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04))) | (unit & 0xfb));
    unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04)) << 3) | (unit & 0xdf));

    /*
     * swap bit[4] and bit[3]
     */
    unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08)) << 1) | (unit & 0xef));
    unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08))) | (unit & 0xf7));
    unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08)) << 1) | (unit & 0xef));

    return unit;
}

3

এটি কি দ্রুত সমাধান হতে পারে?

int byte_to_be_reversed = 
    ((byte_to_be_reversed>>7)&0x01)|((byte_to_be_reversed>>5)&0x02)|      
    ((byte_to_be_reversed>>3)&0x04)|((byte_to_be_reversed>>1)&0x08)| 
    ((byte_to_be_reversed<<7)&0x80)|((byte_to_be_reversed<<5)&0x40)|
    ((byte_to_be_reversed<<3)&0x20)|((byte_to_be_reversed<<1)&0x10);

লুপের জন্য ব্যবহারের তাড়না থেকে মুক্তি পান! তবে বিশেষজ্ঞরা দয়া করে আমাকে বলুন এটি কার্যকর এবং দ্রুত কিনা?


এটি কার্যকর করার সময় ও (লগ এন) এর চেয়ে ও (এন) হয়, যেখানে এন বিটের সংখ্যা (8, 16, 32, 64, ইত্যাদি)। ও (লগ এন) সময়ে কার্যকর হওয়া উত্তরগুলির জন্য অন্য কোথাও দেখুন।
টড লেহম্যান

2

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

যদি এই ধরণের নির্দেশিকাটি পাওয়া না যায়, তবে আমি অনুসন্ধান টেবিল রুটের সাথে যাওয়ার পরামর্শ দেব। আপনার জন্য টেবিলটি তৈরি করতে আপনি কোনও স্ক্রিপ্ট / প্রোগ্রাম লিখতে পারেন এবং এখানে অনুসন্ধানের কাজগুলি যে কোনও বিট-রিভার্জিং অ্যালগরিদমের চেয়ে দ্রুত হবে (কোথাও লুকিং টেবিলটি সংরক্ষণ করার ব্যয়ে)।


2

এই সাধারণ ফাংশনটি ইনপুট বাইটে প্রতিটি বিট পরীক্ষা করতে এবং এটিকে স্থানান্তরিত আউটপুটে স্থানান্তর করতে একটি মাস্ক ব্যবহার করে:

char Reverse_Bits(char input)
{    
    char output = 0;

    for (unsigned char mask = 1; mask > 0; mask <<= 1)
    {
        output <<= 1;

        if (input & mask)
            output |= 1;
    }

    return output;
}

মুখোশ সই করা উচিত দুঃখিত।
luci88filter

1

এই এক এক উপর ভিত্তি করে তৈরি BobStein-VisiBone প্রদান

#define reverse_1byte(b)    ( ((uint8_t)b & 0b00000001) ? 0b10000000 : 0 ) | \
                            ( ((uint8_t)b & 0b00000010) ? 0b01000000 : 0 ) | \
                            ( ((uint8_t)b & 0b00000100) ? 0b00100000 : 0 ) | \
                            ( ((uint8_t)b & 0b00001000) ? 0b00010000 : 0 ) | \
                            ( ((uint8_t)b & 0b00010000) ? 0b00001000 : 0 ) | \
                            ( ((uint8_t)b & 0b00100000) ? 0b00000100 : 0 ) | \
                            ( ((uint8_t)b & 0b01000000) ? 0b00000010 : 0 ) | \
                            ( ((uint8_t)b & 0b10000000) ? 0b00000001 : 0 ) 

আমি সত্যিই এটিকে অনেক পছন্দ করি কারণ সংকলকটি স্বয়ংক্রিয়ভাবে আপনার জন্য কাজটি পরিচালনা করে, সুতরাং আর কোনও সংস্থান প্রয়োজন।

এটি 16-বিট পর্যন্তও বাড়ানো যেতে পারে ...

#define reverse_2byte(b)    ( ((uint16_t)b & 0b0000000000000001) ? 0b1000000000000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000000000000010) ? 0b0100000000000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000000000000100) ? 0b0010000000000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000000000001000) ? 0b0001000000000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000000000010000) ? 0b0000100000000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000000000100000) ? 0b0000010000000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000000001000000) ? 0b0000001000000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000000010000000) ? 0b0000000100000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000000100000000) ? 0b0000000010000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000001000000000) ? 0b0000000001000000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000010000000000) ? 0b0000000000100000 : 0 ) | \
                            ( ((uint16_t)b & 0b0000100000000000) ? 0b0000000000010000 : 0 ) | \
                            ( ((uint16_t)b & 0b0001000000000000) ? 0b0000000000001000 : 0 ) | \
                            ( ((uint16_t)b & 0b0010000000000000) ? 0b0000000000000100 : 0 ) | \
                            ( ((uint16_t)b & 0b0100000000000000) ? 0b0000000000000010 : 0 ) | \
                            ( ((uint16_t)b & 0b1000000000000000) ? 0b0000000000000001 : 0 ) 

আমি bযদি একটি একক সংখ্যার চেয়ে জটিল ভাব প্রকাশের ক্ষেত্রে বন্ধনীগুলিতে রাখি তবে সম্ভবত ম্যাক্রোর পরিবর্তিত REVERSE_BYTEএকটি ইঙ্গিত হিসাবে আপনি সম্ভবত সেখানে আরও জটিল (রানটাইম) এক্সপ্রেশন রাখতে চান না। অথবা এটিকে একটি ইনলাইন ফাংশন করুন। (তবে সামগ্রিকভাবে আমি এটিকে এত সহজ বলে পছন্দ করি যে খুব সহজেই আপনি ভুলের খুব কম সম্ভাবনা সহ স্মৃতি থেকে এটি করতে পারেন))
আরক্কু

1

ধরে নিচ্ছি যে আপনার সংকলকটি স্বাক্ষরবিহীন দীর্ঘ দীর্ঘ অনুমতি দেয় :

unsigned char reverse(unsigned char b) {
  return (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;
}

এখানে আবিষ্কার


1

আপনি যদি ছোট মাইক্রোকন্ট্রোলার ব্যবহার করেন এবং ছোট পায়ের ছাপ সহ উচ্চ গতির সমাধানের প্রয়োজন হয় তবে এটি সমাধান হতে পারে। এটি সি প্রকল্পের জন্য ব্যবহার করা সম্ভব তবে আপনার সি প্রকল্পে আপনার এই ফাইলটি এসেম্বলার ফাইল * .asm হিসাবে যুক্ত করা দরকার। নির্দেশাবলী: সি প্রকল্পে এই ঘোষণাটি যুক্ত করুন:

extern uint8_t byte_mirror(uint8_t);

সি থেকে এই ফাংশন কল করুন

byteOutput= byte_mirror(byteInput);

এটি কোড, এটি কেবল 8051 কোরের জন্য উপযুক্ত। সিপিইউতে রেজিস্টারে আর0 হচ্ছে বাইটইনপুট থেকে প্রাপ্ত ডেটা । কোড অধিকার ঘোরাতে r0 ক্রস বহন এবং তারপর ঘোরান বহন বামে R1 । প্রতিটি বিট জন্য এই পদ্ধতিটি 8 বার পুনরাবৃত্তি করুন। তারপরে রেজিস্টার আর 1 বাইটআউটপুট হিসাবে সি ফাংশনে ফিরে আসবে। 8051 সালে কোর শুধুমাত্র ঘোরান acumulator করার posibble হয় একটি

NAME     BYTE_MIRROR
RSEG     RCODE
PUBLIC   byte_mirror              //8051 core        

byte_mirror
    mov r3,#8;
loop:   
    mov a,r0;
    rrc a;
    mov r0,a;    
    mov a,r1;
    rlc a;   
    mov r1,a;
    djnz r3,loop
    mov r0,a
    ret

পেশাদাররা: এটি ছোট পদক্ষেপ, এটি উচ্চ গতির কনস: এটি পুনরায় ব্যবহারযোগ্য কোড নয়, এটি কেবল ৮০৫১ এর জন্য

011101101-> বহন

101101110 <-carry


এই কোডটি প্রশ্নের উত্তর দিতে পারে, তবে এটি কীভাবে কাজ করে এবং কখন এটি ব্যবহার করবে তা ব্যাখ্যা করে কিছু প্রসঙ্গ অন্তর্ভুক্ত করা ভাল। কোড-কেবল উত্তরগুলি দীর্ঘমেয়াদে কার্যকর নয়।
এফনেক

0
  xor ax,ax
  xor bx,bx
  mov cx,8
  mov al,original_byte!
cycle:   shr al,1
  jnc not_inc
  inc bl
not_inc: test cx,cx
  jz,end_cycle
  shl bl,1
  loop cycle
end_cycle:

বিপরীত বাইট হতে হবে BL রেজিস্টার


3
অন্য কোনও প্রসঙ্গে যা সঠিক উত্তর হতে পারে তবে প্রশ্নটি সি বা সি ++ সম্পর্কিত ছিল, এএসএম নয় ...
জাডাস্ক

0
typedef struct
{
    uint8_t b0:1;
    uint8_t b1:1;
    uint8_t b2:1;
    uint8_t b3:1;
    uint8_t b4:1;
    uint8_t b5:1;
    uint8_t b6:1;
    uint8_t b7:1;
} bits_t;

uint8_t reverse_bits(uint8_t src)
{
    uint8_t dst = 0x0;
    bits_t *src_bits = (bits_t *)&src;
    bits_t *dst_bits = (bits_t *)&dst;

    dst_bits->b0 = src_bits->b7;
    dst_bits->b1 = src_bits->b6;
    dst_bits->b2 = src_bits->b5;
    dst_bits->b3 = src_bits->b4;
    dst_bits->b4 = src_bits->b3;
    dst_bits->b5 = src_bits->b2;
    dst_bits->b6 = src_bits->b1;
    dst_bits->b7 = src_bits->b0;

    return dst;
}

একটি স্টাইলিস্টিক নোট হিসাবে, আমি uint8_t1-বিট ক্ষেত্রগুলিকে কিছুটা কুৎসিত ব্যবহার করতে দেখতে পেয়েছি , যেহেতু এটি প্রথম বলে মনে হয় যে এটি 8 টি বিট নেবে তবে লাইনের শেষে এটি কেবলমাত্র একটি বিট হিসাবে সংজ্ঞায়িত হবে। আমি unsigned b0:1ইত্যাদি ব্যবহার করব
আরক্কু

0
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i;
    unsigned char rev = 0x70 ; // 0b01110000
    unsigned char tmp = 0;

    for(i=0;i<8;i++)
    {
    tmp |= ( ((rev & (1<<i))?1:0) << (7-i));
    }
    rev = tmp;

    printf("%x", rev);       //0b00001110 binary value of given number
    return 0;
}

দয়া করে কিছু ব্যাখ্যা যুক্ত করুন।
zcui93

0

আমি মনে করি এটি যথেষ্ট সহজ

uint8_t reverse(uint8_t a)
{
  unsigned w = ((a << 7) & 0x0880) | ((a << 5) & 0x0440) | ((a << 3) & 0x0220) | ((a << 1) & 0x0110);
  return static_cast<uint8_t>(w | (w>>8));
}

অথবা

uint8_t reverse(uint8_t a)
{
  unsigned w = ((a & 0x11) << 7) | ((a & 0x22) << 5) | ((a & 0x44) << 3) | ((a & 0x88) << 1);
  return static_cast<uint8_t>(w | (w>>8));
}

0
unsigned char c ; // the original
unsigned char u = // the reversed
c>>7&0b00000001 |
c<<7&0b10000000 |
c>>5&0b00000010 |
c<<5&0b01000000 |
c>>3&0b00000100 |
c<<3&0b00100000 |
c>>1&0b00001000 |
c<<1&0b00010000 ;

Explanation: exchanged bits as per the arrows below.
01234567
<------>
#<---->#
##<-->##
###<>###

0

আমি আমার সমাধানটি চিপ করব, যেহেতু আমি এখন পর্যন্ত উত্তরের মতো এর মতো কিছু পাই না। এটি সম্ভবত কিছুটা ওভাররেঞ্জিনারেড তবে এটি std::index_sequenceসংকলনের সময় C ++ 14 ব্যবহার করে দেখার সারণী উত্পন্ন করে ।

#include <array>
#include <utility>

constexpr unsigned long reverse(uint8_t value) {
    uint8_t result = 0;
    for (std::size_t i = 0, j = 7; i < 8; ++i, --j) {
        result |= ((value & (1 << j)) >> j) << i;
    }
    return result;
}

template<size_t... I>
constexpr auto make_lookup_table(std::index_sequence<I...>)
{
    return std::array<uint8_t, sizeof...(I)>{reverse(I)...};   
}

template<typename Indices = std::make_index_sequence<256>>
constexpr auto bit_reverse_lookup_table()
{
    return make_lookup_table(Indices{});
}

constexpr auto lookup = bit_reverse_lookup_table();

int main(int argc)
{
    return lookup[argc];
}

https://godbolt.org/z/cSuWhF


0

এখানে একটি সহজ এবং পঠনযোগ্য সমাধান রয়েছে, যাঁর সাথে রয়েছে এমন সমস্ত প্ল্যাটফর্মগুলির জন্য পোর্টেবল sizeof(char) == sizeof(int):

#include <limits.h>

unsigned char reverse(unsigned char c) {
    int shift;
    unsigned char result = 0;

    for (shift = 0; shift < CHAR_BIT; shift++) {
        result <<= 1;
        result |= c & 1;
        c >>= 1;
    }
    return result;
}

0

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

#include <algorithm>
#include <bitset>
#include <exception>
#include <iostream>
#include <limits>
#include <string>

// helper lambda function template
template<typename T>
auto getBits = [](T value) {
    return std::bitset<sizeof(T) * CHAR_BIT>{value};
};

// Function template to flip the bits
// This will work on integral types such as int, unsigned int,
// std::uint8_t, 16_t etc. I did not test this with floating
// point types. I chose to use the `bitset` here to convert
// from T to string as I find it easier to use than some of the
// string to type or type to string conversion functions,
// especially when the bitset has a function to return a string. 
template<typename T>
T reverseBits(T& value) {
    static constexpr std::uint16_t bit_count = sizeof(T) * CHAR_BIT;

    // Do not use the helper function in this function!
    auto bits = std::bitset<bit_count>{value};
    auto str = bits.to_string();
    std::reverse(str.begin(), str.end());
    bits = std::bitset<bit_count>(str);
    return static_cast<T>( bits.to_ullong() );
}

// main program
int main() {
    try {
        std::uint8_t value = 0xE0; // 1110 0000;
        std::cout << +value << '\n'; // don't forget to promote unsigned char
        // Here is where I use the helper function to display the bit pattern
        auto bits = getBits<std::uint8_t>(value);
        std::cout << bits.to_string() << '\n';

        value = reverseBits(value);
        std::cout << +value << '\n'; // + for integer promotion

        // using helper function again...
        bits = getBits<std::uint8_t>(value);
        std::cout << bits.to_string() << '\n';

    } catch(const std::exception& e) {  
        std::cerr << e.what();
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

এবং এটি নিম্নলিখিত আউটপুট দেয়।

224
11100000
7
00000111

0

এইটি আমাকে 8x8 ডট ম্যাট্রিক্স সেট অ্যারে সাহায্য করেছে।

uint8_t mirror_bits(uint8_t var)
{
    uint8_t temp = 0;
    if ((var & 0x01))temp |= 0x80;
    if ((var & 0x02))temp |= 0x40;
    if ((var & 0x04))temp |= 0x20;
    if ((var & 0x08))temp |= 0x10;

    if ((var & 0x10))temp |= 0x08;
    if ((var & 0x20))temp |= 0x04;
    if ((var & 0x40))temp |= 0x02;
    if ((var & 0x80))temp |= 0x01;

    return temp;
}

1
এই ফাংশনটি আসলে কাজ করে না, 0b11001111 এর বিপরীতে 0b11110011 হওয়া উচিত, তবে এই ফাংশনটিতে ব্যর্থ হয়। এখানে তালিকাভুক্ত অন্যান্য ফাংশনগুলির জন্য একই পরীক্ষার পদ্ধতি কাজ করে।
ড্যান

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