2011-01-31 13 views
74

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

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

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

उत्तर

136

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

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

संपादित करें: थोड़ा और विस्तार को जोड़ने के लिए, क्योंकि वहाँ कोई स्पष्टीकरण के साथ इसी तरह के जवाब का एक बहुत हैं:

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

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 

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

+7

गायब ब्रेसिज़ (ऑपरेटर प्राथमिकता) के कारण यह कोड संकलित नहीं होता है, यह 'var bit = (b & (1 << bitNumber-1)) होना चाहिए! = 0'; अंतर्निहित समाधान के लिए – bitbonk

3

इस प्रयास करें:

return (b & (1 << bitNumber))>0; 
31

यह

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

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

43

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

+6

+1। :) – Sapph

+0

यह शानदार है लेकिन मेरा मानना ​​है कि जोश का समाधान बहुत तेज़ और अधिक कुशल है। –

+0

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

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

यह कर का एक और तरीका :)

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

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

+0

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

+0

मुझे विश्वास नहीं है कि वह सभी @ डेविड एंड्रिया पर है, राफेल द्वारा पोस्ट की गई टिप्पणी सही मानती है कि थोड़ा सा थोड़ा सा है, लेकिन पियरोज़ का कोड तब होता है जब सही सबसे थोड़ा सा 0 होता है। यदि बी 2 था, फिर '((2 >> 1) और 1)' '1' और' ((2 >> 0) और 1) '''' है क्योंकि 2' 00000010' –

2

नीचे कोड की कोशिश करो। अन्य पदों के साथ अंतर यह है कि आप मास्क (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 
7

BitArray वर्ग का उपयोग करना और एक विस्तार विधि बनाने के रूप में ओ पी पता चलता है:

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

नहीं है, कृपया न बनाएं और फेंक दें प्रत्येक बिट परीक्षण के लिए बिटएरे। –

+0

@BenVoigt, यह प्रति बाइट प्रति ओपी अनुरोध पर एक विस्तार विधि है। आप BitArray उदाहरण को संग्रहीत करने की अनुशंसा करते हैं? –

+2

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

2

यह वह जगह है तेजी से 0.1 मिलीसेकंड से काम करता है।

return (b >> bitNumber) & 1;