bugfixr
bugfixr

Reputation: 8077

C#, bits & bytes - How do I retrieve bit values from a byte?

I'm reading some values from a single byte. I'm told in the user-manual that this one byte contains 3 different values. There's a table that looks like this:

bit table

I interpret that has meaning precision takes up 3 bits, scale takes up 2 and size takes up 3 for a total of 8 (1 byte).

What I'm not clear on is:

1 - Why is it labeled 7 through 0 instead of 0 through 7 (something to do with significance maybe?)

2 - How do I extract the individual values out of that one byte?

Upvotes: 16

Views: 21490

Answers (5)

BlackBear
BlackBear

Reputation: 22979

You can do this via bitwise arithmetic:

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

Upvotes: 2

Mark Byers
Mark Byers

Reputation: 837926

1. Yes, the most significant bit is usually written first. The left-most bit is labeled 7 because when the byte is interpreted as an integer, that bit has value 27 (= 128) when it is set.

This is completely natural and is in fact is exactly the same as how you write decimal numbers (most significant digit first). For example, the number 356 is (3 x 102) + (5 x 101) + (6 x 100).

2. For completion, as mentioned in other answers you can extract the individual values using the bit shift and bitwise-and operators as follows:

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

Important note: this assumes that the individual values are to be interpreted as positive integers. If the values could be negative then this won't work correctly. Given the names of your variables, this is unlikely to be a problem here.

Upvotes: 4

Crake
Crake

Reputation: 1679

You can do shifts and masks, or you can use the BitArray class: http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx

Example with 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 output:

LINQPad output

Upvotes: 7

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

It is customary to number bits in a byte according to their significance: bit x represents 2^x. According to this numbering scheme, the least significant bit gets number zero, the next bit is number one, and so on.

Getting individual bits requires a shift and a masking operation:

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

Shift by the number of bits to the right of the rightmost portion that you need to get (shifting by zero is ignored; I added it for illustration purposes).

Mask with the highest number that fits in the number of bits that you would like to get: 1 for one bit, 3 for two bits, 7 for three bits, 2^x-1 for x bits.

Upvotes: 22

Wug
Wug

Reputation: 13196

  1. Potayto, potahto.

  2. You'd use shifts and masks to flatten out the undesired bits, like such:

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

Upvotes: 5

Related Questions