Получить определенный бит из байта
У меня есть байт, в частности один байт из массива байтов, который поступает через UDP, отправленный с другого устройства. Этот байт хранит состояние включения/выключения 8 реле в устройстве.
Как мне получить значение определенного бита в указанном байте? В идеале метод расширения выглядел бы наиболее изящным, и возврат bool имел бы для меня самый лучший смысл.
public static bool GetBit(this byte b, int bitNumber)
{
//black magic goes here
}
Ответы
Ответ 1
Легко. Используйте побитовое И, чтобы сравнить ваш номер со значением 2 ^ bitNumber, который можно недорого рассчитать с помощью смещения бит.
//your black magic
var bit = (b & (1 << bitNumber-1)) != 0;
EDIT: Чтобы добавить немного больше деталей, потому что есть много похожих ответов без объяснения:
Побитовое И сравнивает каждое число, побитовое, используя соединение И для создания числа, которое представляет собой комбинацию битов, где были установлены как первый бит, так и второй бит в этом месте. Здесь логическая матрица логики И в "полубайте", которая показывает операцию поразрядного И:
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
Теперь вы знаете, как это делается, что происходит на низком уровне и почему оно работает.
Ответ 2
В то время как хорошо читать и понимать ответ Джоша, вы, вероятно, будете более счастливы, используя класс Microsoft, предоставленный для этой цели: System.Collections.BitArray Он доступен во всех версиях .NET Framework.
Ответ 3
Это
public static bool GetBit(this byte b, int bitNumber) {
return (b & (1 << bitNumber)) != 0;
}
должен это сделать, я думаю.
Ответ 4
другой способ сделать это:)
return ((b >> bitNumber) & 1) != 0;
Ответ 5
Используя BitArray и создавая метод расширения, как предлагает OP:
public static bool GetBit(this byte b, int bitNumber)
{
System.Collections.BitArray ba = new BitArray(new byte[]{b});
return ba.Get(bitNumber);
}
Ответ 6
Это работает быстрее, чем 0,1 миллисекунды.
return (b >> bitNumber) & 1;
Ответ 7
попробуйте следующее:
return (b & (1 << bitNumber))>0;
Ответ 8
Метод заключается в использовании другого байта вместе с побитовым И, чтобы замаскировать целевой бит.
Я использовал соглашение из моих классов здесь, где "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;
}
}
Ответ 9
Этот веб-сайт имеет несколько реализаций того, как получить бит из байта на С#. У этого также есть довольно хорошее объяснение этого. http://bytes.com/topic/c-sharp/answers/505085-reading-bits-byte-file
Ответ 10
Попробуйте выполнить приведенный ниже код. Разница с другими сообщениями заключается в том, что вы можете установить/получить несколько бит с помощью маски (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
Ответ 11
[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);
}