Obtenir un bit spécifique de l’octet

J’ai un octet, en particulier un octet d’un tableau d’octets qui est entré via UDP envoyé à partir d’un autre appareil. Cet octet stocke l’état activé / désactivé de 8 relais dans le périphérique.

Comment puis-je obtenir la valeur d’un bit spécifique dans ledit octet? Idéalement, une méthode d’extension serait la plus élégante et le retour d’un bool me semblerait plus logique.

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

Facile. Utilisez un bit ET pour comparer votre nombre avec la valeur 2 ^ bitNumber, qui peut être calculé à moindre coût par un décalage binary.

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

EDIT: Pour append un peu plus de détails car il y a beaucoup de réponses similaires sans explication:

Un bit AND compare chaque nombre, bit par bit, en utilisant une jointure AND pour produire un nombre qui est la combinaison de bits où le premier bit et le second bit de cet endroit ont été définis. Voici la masortingce logique de la logique AND dans un "quartet" qui montre le fonctionnement d'un bit ET:

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

Dans votre cas, nous comparons le nombre que vous avez passé avec un nombre qui n'a que le bit que vous voulez chercher ensemble. Disons que vous recherchez le quasortingème bit:

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

Le décalage des bits, pour produire le nombre que nous voulons comparer, est exactement ce que cela ressemble: prenez le nombre, représenté comme un ensemble de bits, et déplacez ces bits vers la gauche ou la droite d'un certain nombre de lieux. Comme il s'agit de nombres binarys et que chaque bit est une puissance supérieure à deux, le décalage binary vers la gauche équivaut à doubler le nombre une fois pour chaque place décalée, ce qui équivaut à multiplier le nombre par 2 ^ x. Dans votre exemple, en recherchant le quasortingème bit, nous effectuons:

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

Maintenant, vous savez comment cela se passe, ce qui se passe au bas niveau et pourquoi cela fonctionne.

Bien qu’il soit bon de lire et de comprendre la réponse de Josh, vous serez probablement plus heureux d’utiliser la classe Microsoft fournie à cet effet: System.Collections.BitArray Elle est disponible dans toutes les versions de .NET Framework.

Ce

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

devrait le faire, je pense.

une autre façon de le faire 🙂

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

L’ utilisation de la classe BitArray et la création d’une méthode d’extension comme OP suggèrent:

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

Cela fonctionne plus vite que 0,1 milliseconde.

 return (b >> bitNumber) & 1; 

essaye ça:

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

La méthode consiste à utiliser un autre octet avec un bit ET pour masquer le bit cible.

J’ai utilisé la convention de mes classes ici où “0” est le bit le plus significatif et “7” le moins.

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

Ce site Web a plusieurs implémentations sur la manière d’obtenir un peu d’un octet en C #. Cela a aussi une bonne explication à ce sujet. http://bytes.com/topic/c-sharp/answers/505085-reading-bits-byte-file

Essayez le code ci-dessous. La différence avec les autres articles est que vous pouvez définir / obtenir plusieurs bits en utilisant un masque ( field ). Le masque du 4ème bit peut être 1 << 3 ou 0x10, par exemple.

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

** Exemple **

  bool is_ok = 0x01AF.GetBits(0x10); //false int res = 0x01AF.SetBits(0x10, true); is_ok = res.GetBits(0x10); // true 
 [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); }