Получить определенный бит из байта


У меня есть байт, в частности один байт из массива байтов, который пришел через UDP, отправленный с другого устройства. Этот байт сохраняет состояние включения / выключения 8 реле в устройстве.

Как мне получить значение определенного бита в байте? В идеале метод расширения будет выглядеть наиболее элегантно и возврат bool имеет смысл для меня.

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

11 ответов:

легко. Используйте побитовое число и сравните свое число со значением 2^bitNumber, которое можно дешево вычислить путем сдвига битов.

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

EDIT: чтобы добавить немного больше деталей, потому что есть много подобных ответов без объяснения причин:

побитовое и сравнивает каждое число, бит за битом, используя AND join для получения числа, которое является комбинацией битов, где были установлены как первый бит, так и второй бит в этом месте. Вот логическая матрица и логики в "грызть", что показывает работу побитового и:

  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^x. в вашем примере, ища четвертый бит, мы выполняем:

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

теперь вы знаете, как это делается, что происходит на низком уровне, и почему это работает.

хотя хорошо читать и понимать ответ Джоша, вы, вероятно, будете счастливее, используя класс Microsoft, предоставленный для этой цели:

этой

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

должен сделать это, я думаю.

другой способ сделать это :)

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

С помощью BitArray класс и создание метода расширения, как предлагает OP:

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

это работает быстрее, чем 0,1 мс.

return (b >> bitNumber) & 1;

попробуйте это:

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

метод состоит в том, чтобы использовать другой байт вместе с побитовым и замаскировать целевой бит.

я использовал соглашение из моих классов здесь, где" 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;
    }
}

этот сайт имеет несколько реализаций, как получить бит из байта в C#. Она также имеет довольно хорошее объяснение этого. http://bytes.com/topic/c-sharp/answers/505085-reading-bits-byte-file

попробуйте код ниже. Разница с другими сообщениями заключается в том, что вы можете установить/получить несколько битов с помощью маски (field). Маска для 4-го бита может быть 1

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