views:

472

answers:

5

Hello quick question regarding bit shifting

I have a value in HEX = new byte[] { 0x56, 0xAF };

which is 0101 0110 1010 1111

i want to the first n bits, example 12

then shift off the remaining 4 (16-12) to get 0000 0101 0110 1010 (1386 dec)

i cant wrap my head around it and make it scalable for n bits.

Thanks!

+1  A: 

You can use a BitArray and then easily copy each bit to the right, starting from the right.

http://msdn.microsoft.com/en-us/library/system.collections.bitarray%5Fmethods.aspx

Unknown
A: 

you want something like...

var HEX = new byte[] {0x56, 0xAF};
var bits = new BitArray(HEX);
int bitstoShiftRight = 4;
for (int i = 0; i < bits.Length; i++)
{
   bits[i] = i < (bits.Length - bitstoShiftRight) ? bits[i + bitstoShiftRight] : false;
}
bits.CopyTo(HEX, 0);
Keith Nicholas
thanks, i liked this approach, issue being is that BitArray constructor changed the order of the Endian per byte which the value was then wrong once the method finished, id need to reverse the bit order per byte before instantiating the bit-array with the byes
Bobby
A: 

If you have k total bits, and you want the "first" (as in most significant) n bits, you can simply right shift k-n times. The last k-n bits will be removed, by sort of "falling" off the end, and the first n will be moved to the least significant side.

NickJohnson
Thanks for the response, problem is that i cant really bit shift an array of bytes, i need to do them individually and then i lose the overflow, so my alternative was to cast the whole 16 bits to a int 16 and shift at that point, no what i wanted since i now need to know the length and cast to that type then shift
Bobby
A: 

Answering using C-like notation, assuming bits_in_byte is the number of bits in a byte determined elsewhere:

int remove_bits_count= HEX.count*bits_in_byte - bits_to_keep;
int remove_bits_in_byte_count= remove_bits_count % bits_in_byte;

if (remove_bits_count > 0)
{
 for (int iteration= 0; iteration<min(HEX.count, (bits_to_keep + bits_in_byte - 1)/bits_in_byte); ++iteration)
 {
  int write_index= HEX.count - iteration - 1;
  int read_index_lo= write_index - remove_bits_count/bits_in_byte;

  if (read_index_lo>=0)
  {
   int read_index_hi= read_index_lo - (remove_bits_count + bits_in_byte - 1)/bits_in_byte;

   HEX[write_index]= 
    (HEX[read_index_lo] >> remove_bits_in_byte_count) | 
    (HEX[read_index_hi] << (bits_in_byte - remove_bits_in_byte_count));
  }
  else
  {
   HEX[write_index]= 0;
  }
 }
}

Assuming you are overwriting the original array, you basically take every byte you write to and figure out the bytes that it would get its shifted bits from. You go from the end of the array to the front to ensure you never overwrite data you will need to read.

MSN
A: 

Sometime ago i coded these two functions, the first one shifts an byte[] a specified amount of bits to the left, the second does the same to the right:

Left Shift:

    public byte[] ShiftLeft(byte[] value, int bitcount)
 {
  byte[] temp = new byte[value.Length];
  if (bitcount >= 8)
  {
   Array.Copy(value, bitcount / 8, temp, 0, temp.Length - (bitcount / 8));
  }
  else
  {
   Array.Copy(value, temp, temp.Length);
  }
  if (bitcount % 8 != 0)
  {
   for (int i = 0; i < temp.Length; i++)
   {
    temp[i] <<= bitcount % 8;
    if (i < temp.Length - 1)
    {
     temp[i] |= (byte)(temp[i + 1] >> 8 - bitcount % 8);
    }
   }
  }
  return temp;
 }

Right Shift:

    public byte[] ShiftRight(byte[] value, int bitcount)
 {
  byte[] temp = new byte[value.Length];
  if (bitcount >= 8)
  {
   Array.Copy(value, 0, temp, bitcount / 8, temp.Length - (bitcount / 8));
  }
  else
  {
   Array.Copy(value, temp, temp.Length);
  }
  if (bitcount % 8 != 0)
  {
   for (int i = temp.Length - 1; i >= 0; i--)
   {
    temp[i] >>= bitcount % 8;
    if (i > 0)
    {
     temp[i] |= (byte)(temp[i - 1] << 8 - bitcount % 8);
    }
   }
  }
  return temp;
 }

If you need further explanation please comment on this, i will then edit my post for clarification...

haze4real