बाइट से एक विशिष्ट बिट प्राप्त करें


97

मेरे पास एक बाइट है, विशेष रूप से एक बाइट सरणी से एक बाइट जो दूसरे डिवाइस से भेजे गए यूडीपी के माध्यम से आती है। यह बाइट डिवाइस में 8 रिले की चालू / बंद स्थिति को संग्रहीत करता है।

उक्त बाइट में मुझे विशिष्ट बिट का मूल्य कैसे मिलेगा? आदर्श रूप से एक विस्तार विधि सबसे सुरुचिपूर्ण दिखती है और एक बूल लौटकर मुझे सबसे अधिक समझ में आता है।

public static bool GetBit(this byte b, int bitNumber)
{
    //black magic goes here
}

जवाबों:


178

आसान। बिटवाइज़ का उपयोग करें और अपने नंबर की तुलना 2 ^ बिटनंबर के साथ करें, जिसे बिट-शिफ्टिंग द्वारा सस्ते में गणना की जा सकती है।

//your black magic
var bit = (b & (1 << bitNumber-1)) != 0;

संपादित करें: थोड़ा अधिक विवरण जोड़ने के लिए क्योंकि बिना विवरण के बहुत सारे समान उत्तर हैं:

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

  0101
& 0011
  ----
  0001 //Only the last bit is set, because only the last bit of both summands were set

आपके मामले में, हम आपके द्वारा पास की गई संख्या की तुलना करते हैं जिसमें केवल वह बिट है जिसे आप सेट करना चाहते हैं। मान लीजिए कि आप चौथे बिट की तलाश कर रहे हैं:

  11010010
& 00001000
  --------
  00000000 //== 0, so the bit is not set

  11011010
& 00001000
  --------
  00001000 //!= 0, so the bit is set

बिट-शिफ्टिंग, जिस संख्या के खिलाफ हम तुलना करना चाहते हैं उसका उत्पादन करने के लिए, यह वास्तव में ऐसा लगता है: संख्या ले लो, बिट्स के एक सेट के रूप में प्रतिनिधित्व किया, और उन बिट्स को एक निश्चित संख्या में स्थानों द्वारा छोड़ दिया या दाएं स्थानांतरित करें। क्योंकि ये द्विआधारी संख्याएँ हैं और इसलिए प्रत्येक बिट अपने दाईं ओर एक से दो से अधिक पावर-ऑफ है, बिट-शिफ्टिंग को प्रत्येक स्थान पर एक बार स्थानांतरित करने के लिए संख्या को दोगुना करने के बराबर है, जो संख्या को गुणा करने के बराबर है 2 ^ एक्स। आपके उदाहरण में, चौथे बिट की तलाश में, हम प्रदर्शन करते हैं:

       1 (2^0) << (4-1) ==        8 (2^3)
00000001       << (4-1) == 00001000

अब आप जानते हैं कि यह कैसे किया जाता है, निम्न स्तर पर क्या हो रहा है, और यह क्यों काम करता है।


8
लापता ब्रेसिज़ (ऑपरेटर पूर्वता) के कारण यह कोड संकलित नहीं होता है, यह होना चाहिए var bit = (b & (1 << bitNumber-1)) != 0;
बिटकॉइन

54

हालांकि यह जोश के जवाब को पढ़ने और समझने के लिए अच्छा है, आप शायद इस उद्देश्य के लिए प्रदान की गई Microsoft का उपयोग करके खुश होंगे: System.Collections.BitArray यह .NET फ्रेमवर्क के सभी संस्करणों में उपलब्ध है।


1
यह शानदार है लेकिन मेरा मानना ​​है कि जोश का समाधान ज्यादा तेज और अधिक कुशल है।
सैमुअल एलन

1
@ user2332868: JIT कंपाइलर विशेष रूप से कुछ लाइब्रेरी फंक्शंस को कॉल को पहचानता है और कुशल कोड उत्पन्न करता है, लेकिन मुझे नहीं पता कि इन विशेष फंक्शंस को प्यार मिलता है या नहीं।
बेन वोइग्ट

1
अच्छी तरह से यकीन है कि आप जोश के रूप में लेकिन शुद्ध इनलाइन विधानसभा में कर सकते हैं। लेकिन दुख की बात है कि मैं केवल NASM विधानसभा में कार्यक्रम करता हूं और विधानसभा C # के बारे में नहीं जानता :(।
शमूएल एलन

1
IMHO इस तरह के एक सरल कार्य के लिए प्रदर्शन को मारता है। बिटवाइज़ ऑपरेटर विकल्प का उपयोग करने से आपको एक टूल भी मिलता है जिसे आप लगभग किसी भी भाषा में उपयोग कर सकते हैं =)
Gaspa79

38

यह

public static bool GetBit(this byte b, int bitNumber) {
   return (b & (1 << bitNumber)) != 0;
}

मुझे यह करना चाहिए, मुझे लगता है।


9

इसे करने का दूसरा तरीका :)

return ((b >> bitNumber) & 1) != 0;

1
यह काम नहीं करेगा: बाइट बी = 1; वापसी ((बी >> 1) और 1)! = 0 (यह 0 के बराबर है)
राफेल डिएगो निकोलेटी

1
हममम ... मैं तुम्हें नहीं मिलता। यदि बाइट बी = 1, स्थिति 0 पर बिट 1 है, (बी >> 0) और 1 के आधार पर दिया गया है, और किसी भी स्थिति में 1 या उससे अधिक के बराबर बिट 0 (बी >> एन) और 1 द्वारा दिया गया है, जहां n> = 1 साथ ही
पियरोज़

मैं नहीं मानता कि उसके सारे @DavideAndrea पर, टिप्पणी राफेल द्वारा पोस्ट की गई मानता है कि सबसे-दाएं बिट बिट है 1, लेकिन PierrOz के कोड सही सबसे बिट बिट है जब 0. के लिए है, तो बी 2 था करता है, तो ((2 >> 1)&1)है 1और ((2 >> 0)&1)है 0क्योंकि 2 है00000010
कैमरून Aavik


6

BitArray वर्ग का उपयोग करना और OP के रूप में एक विस्तार विधि बनाना:

public static bool GetBit(this byte b, int bitNumber)
{
    System.Collections.BitArray ba = new BitArray(new byte[]{b});
    return ba.Get(bitNumber);
}

9
नहीं, कृपया प्रत्येक बिट परीक्षण के लिए एक BitArray बनाएँ और न फेंकें।
बेन वोइग्ट

@BenVoigt, यह ओपी अनुरोध प्रति बाइट पर एक विस्तार विधि है। आप BitArray उदाहरण के भंडारण की सलाह कहाँ देते हैं?
जे वॉकर

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

यदि आप एक बाइट की nth बिट प्राप्त करना चाहते हैं, तो आप प्रदर्शन की सबसे अधिक संभावना है, और यह इसे मारता है। अन्यथा आप हमेशा अन्य अनावश्यक चीजें कर सकते हैं जैसे Convert.ToString (संख्या, 2) [बिटनंबर] और इसे भी प्राप्त करें।
गस्पा 79


3

विधि एक और बाइट के साथ-साथ एक बिटवाइज़ और लक्ष्य बिट को बाहर निकालने के लिए उपयोग करना है।

मैंने अपने वर्गों से सम्मेलन का उपयोग किया जहां "0" सबसे महत्वपूर्ण बिट है और "7" सबसे कम है।

public static class ByteExtensions
{
    // Assume 0 is the MSB andd 7 is the LSB.
    public static bool GetBit(this byte byt, int index)
    {
        if (index < 0 || index > 7)
            throw new ArgumentOutOfRangeException();

        int shift = 7 - index;

        // Get a single bit in the proper position.
        byte bitMask = (byte)(1 << shift);

        // Mask out the appropriate bit.
        byte masked = (byte)(byt & bitMask);

        // If masked != 0, then the masked out bit is 1.
        // Otherwise, masked will be 0.
        return masked != 0;
    }
}

3

नीचे दिए गए कोड का प्रयास करें। अन्य पदों के साथ अंतर यह है कि आप मास्क ( field) का उपयोग करके कई बिट्स सेट / प्राप्त कर सकते हैं । 4 बिट के लिए मुखौटा 1 << 3, या 0x10 हो सकता है, उदाहरण के लिए।

    public int SetBits(this int target, int field, bool value)
    {
        if (value) //set value
        {
            return target | field;
        }
        else //clear value
        {
            return target & (~field);
        }
    }

    public bool GetBits(this int target, int field)
    {
        return (target & field) > 0;
    }

** उदाहरण **

        bool is_ok = 0x01AF.GetBits(0x10); //false
        int res = 0x01AF.SetBits(0x10, true);
        is_ok = res.GetBits(0x10);  // true

2
[Flags]
enum Relays : byte
{
    relay0 = 1 << 0,
    relay1 = 1 << 1,
    relay2 = 1 << 2,
    relay3 = 1 << 3,
    relay4 = 1 << 4,
    relay5 = 1 << 5,
    relay6 = 1 << 6,
    relay7 = 1 << 7
}

public static bool GetRelay(byte b, Relays relay)
{
    return (Relays)b.HasFlag(relay);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.