Подтвердить что ты не робот

С#, bits & bytes - Как получить битовые значения из байта?

Я читаю некоторые значения из одного байта. Мне сказано в руководстве пользователя, что этот байт содержит 3 разных значения. Вот таблица, которая выглядит так:

bit table

Я интерпретирую, что точность значения занимает 3 бита, масштаб занимает 2, а размер занимает 3 в общей сложности 8 (1 байт).

Я не понимаю, что:

1 - Почему это помечено 7 через 0 вместо 0-7 (что-то, что может иметь значение, возможно?)

2 - Как извлечь отдельные значения из этого байта?

4b9b3361

Ответ 1

Обычно принято биты в байтах в соответствии с их значением: бит x представляет 2^x. Согласно этой схеме нумерации младший значащий бит получает номер нуль, следующий бит - номер один и т.д.

Получение отдельных бит требует операции сдвига и маскировки:

var size = (v >> 0) & 7;
var scale = (v >> 3) & 3;
var precision = (v >> 5) & 7;

Сдвиг по количеству бит справа от самой правой части, которую нужно получить (смещение на ноль игнорируется, я добавил его для иллюстрации).

Маска с наибольшим числом, которое соответствует количеству битов, которые вы хотели бы получить: 1 для одного бита, 3 для двух бит, 7 для трех бит, 2^x-1 для x бит.

Ответ 2

Вы можете делать смены и маски, или вы можете использовать класс BitArray: http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx

Пример с BitVector32:

BitVector32 bv = new BitVector32(0);

var size = BitVector32.CreateSection(7);
var scale = BitVector32.CreateSection(3, size);
var precision = BitVector32.CreateSection(7, scale);

bv[size] = 5;
bv[scale] = 2;
bv[precision] = 4;

Выход LINQPad:

LINQPad output

Ответ 3

  • Potayto, potahto.

  • Вы должны использовать сдвиги и маски для выравнивания нежелательных бит, например:

    byte b = something; // b is our byte
    
    int size = b & 0x7;
    int scale = (b >> 3) & 0x3;
    int position = (b >> 5) & 0x7;
    

Ответ 4

1. Да, самый старший бит обычно записывается первым. Самый левый бит обозначается 7, потому что, когда байт интерпретируется как целое число, этот бит имеет значение 2 7 (= 128), когда он установлен.

Это совершенно естественно и на самом деле точно так же, как и то, как вы пишете десятичные числа (сначала самая значимая цифра). Например, число 356 равно (3 x 10 2) + (5 x 10 1) + ( 6 x 10 0).

2. Для завершения, как упоминалось в других ответах, вы можете извлекать отдельные значения с помощью сдвига бит и побитового и операторов следующим образом:

int size = x & 7;
int scale = (x >> 3) & 3;
int precision = (x >> 5) & 7;

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

Ответ 5

Вы можете сделать это с помощью побитовой арифметики:

uint precision = (thatByte & 0xe0) >> 5,
    scale = (thatByte & 0x18) >> 3,
    size = thatByte & 7;