Set Specific Bit in Byte Array - c#

I want to know how to set a specific bit in a 16 byte array (128 bits).
For example ... if I wanted to set the 9th bit in the the array I would expect:
{00, 80, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}
If I wanted to set the 125th bit ...
{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 08}
I have looked into using bit shifting but got confused on how to bit shift with an array consisting of 128 bits. Is there a way to break down an array this size and evaluate in smaller chunks of bytes? Any help would be appreciated.

The process of selecting a specific bit consists of two steps:
Picking the byte, and then
Picking the bit.
Picking the byte is simple: all you need to do is dividing the bit index by the number of bits in a byte - i.e. dividing by eight:
int byteIndex = bitIndex / 8;
Now that you know what byte to use, calculate which bit you want to access. For that you need to compute a remainder of a division by eight, like this:
int bitInByteIndex = bitIndex % 8;
With these two indexes in hand, it is easy to access the bit: use 1 << bitInByteIndex as a mask, like this:
byte mask = (byte)(1 << bitInByteIndex);
bool isSet = (bytes[byteIndex] & mask) != 0;
// set to 1
bytes[byteIndex] |= mask;
// Set to zero
bytes[byteIndex] &= ~mask;
// Toggle
bytes[byteIndex] ^= mask;

You could use a BitArray:
byte[] bytearray = new byte[16];
var bitArray = new BitArray(bytearray);
bitArray.Set(8, true);
bitArray.CopyTo(bytearray, 0);

Directly from a Byte Array, your quickest solution is probably using a BitArray.
- http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx
E.g. This would go something like:
public void BitManimulation()
{
//Ill just use 2 bytes here for demonstration, get your 16 bytes here.
byte[] bytes = new[] { (byte)250, (byte)250 };
//Convert your bytes to a BitArray.
BitArray array = new BitArray(bytes);
array[3] = !array[3]; // Flip
array[4] = false; // 0
array[5] = true; // 1
//Convert back to bytes.
byte[] bytes2 = new byte[2];
array.CopyTo(bytes2,0);
Console.WriteLine(bytes2[0]);
Console.WriteLine(bytes2[1]);
}
Now this comes with a performance penalty.
So as an alternative you have the BitVector32 that will require you to convert blocks of 4 bytes to an integer...
- http://msdn.microsoft.com/en-us/library/system.collections.specialized.bitvector32.aspx
Finally you can do bit shifting, XOR's etc to produce the desired results. Since #dasblinkenlight already left a nice answer for that ill just leave you with that for explaining things.^
Here is some quick helper methods based on his post though:
public static class ByteArrayExt
{
public static byte[] SetBit(this byte[] self, int index, bool value)
{
int byteIndex = index / 8;
int bitIndex = index % 8;
byte mask = (byte)(1 << bitIndex);
self[byteIndex] = (byte)(value ? (self[byteIndex] | mask) : (self[byteIndex] & ~mask));
return self;
}
public static byte[] ToggleBit(this byte[] self, int index)
{
int byteIndex = index / 8;
int bitIndex = index % 8;
byte mask = (byte)(1 << bitIndex);
self[byteIndex] ^= mask;
return self;
}
public static bool GetBit(this byte[] self, int index)
{
int byteIndex = index / 8;
int bitIndex = index % 8;
byte mask = (byte)(1 << bitIndex);
return (self[byteIndex] & mask) != 0;
}
}

First you need to find out which byte you're working with. Let's say you have:
00000000 00000000 00000000 00000000 ...
And you want to turn on the 10th bit, so it needs to become like this:
00000000 01000000 00000000 00000000 ...
So first do a division by 8 (rounded down) to locate the byte number (in this case byte number one, or the second byte). Once you've done that, you can use bitwise operators to set the bit you want, i.e.
array[1] |= 0x40
We're doing a bitwise OR operation between the old value of that byte and 0x40 (which is 01000000). If the old value was 00101101, then array[1] = (00101101 OR 01000000), which is 01101101.
Naturally, in this case I've been using literals so you'll have to change that depending on which bit is set (e.g. if you're setting the bit before the last, you want to use 0x02 instead, etc.

Dividing the bit number by 8 gives you the byte. Taking it modulo 8 give you the bit number within the byte.

You can also use lookUp, like this:
byte[] lookUp = { 1, 2, 4, 8, 16, 32, 64, 128 };
And the following code (considering reverse bits numeration in bytes)
int bytePosition = bitIndex / 8;
int bitInBytePosition = bitIndex % 8;
if (bitIndex < 8)
{
bitInBytePosition = bitIndex;
}
array[bytePosition] ^= lookUp[7 - bitInBytePosition];

Related

Split 32 bits integer into 4 parts

i've a byte array of size 16384(SourceArray). i want to split it into 4 parts,4 byte array of size 4096. Now each 32 bits from SourceArray will be divided into 10 bits,10 bits,11 bits and 1 bit (10+10+11+1=32 bits). Taking first 10bits,then next 10bits then 11bits and then 1bit.
lets say for example first 4 bytes from the sourceArray, i get a value 9856325. Now 9856325(dec) = 00000000100101100110010101000101(Binary)-----------------------------
0000000010(10bits) 0101100110(10bits) 01010100010(11bits) 1(1bit). I cannot store 10,10,11 bits in byte array, So i'm storing it into Int16 array and for 1 bit i can store it into a byte array.
`
I hope problem statement is clear. I've created some logic.
Int16[] Array1 = new Int16[4096];
Int16[] Array2 = new Int16[4096];
Int16[] Array3 = new Int16[4096];
byte[] Array4 = new byte[4096];
byte[] SourceArray = File.ReadAllBytes(#"Reading an image file from directory");
//Size of source Array = 16384
for (int i = 0; i < 4096; i++)
{
uint temp = BitConverter.ToUInt32(SourceArray, i * 4);
uint t = temp;
Array1[i] = (Int16)(t >> 22);
t = temp << 10;
Array2[i] = (Int16)(t >> 22);
t = temp << 20;
Array3[i] = (Int16)(t >> 21);
t = temp << 31;
Array4[i] = (byte)(t>>31);
}
But i'm not getting the actual results. i might be missing something in my logic. Please verify it, whats wrong Or if you have some better logic,please suggest me.
In my opinion much easier to process bits starting from the last (least significant bit):
uint t = BitConverter.ToUInt32(SourceArray, i * 4);
Array4[i] = (byte) (t & 0x1);
t >>= 1;
Array3[i] = (Int16) (t & 0x7ff); // 0x7ff - mask for 11 bits
t >>= 11;
Array2[i] = (Int16) (t & 0x3ff); // 0x3ff - mask for 10 bits
t >>= 10;
Array1[i] = (Int16) t; // we don't need mask here
Or in reverse order of bit groups:
uint t = BitConverter.ToUInt32(SourceArray, i * 4);
Array2[i] = (Int16) (t & 0x3ff); // 0x3ff - mask for 10 bits
t >>= 10;
Array2[i] = (Int16) (t & 0x3ff); // 0x3ff - mask for 10 bits
t >>= 10;
Array3[i] = (Int16) (t & 0x7ff); // 0x7ff - mask for 11 bits
t >>= 11;
Array4[i] = (byte) (t & 0x1); // we don't need mask here

Converting 4-byte OLE (VB6) to double/float in C#

Well, I have a 4 (four) bytes array that I need to convert to double data-type (or float) in C#.
I believe that the 4 bytes array is an OLE Automation one.
Tried the following, but no success:
// 1st trial:
double d = BitConverter.ToDouble(b1, 0); // after resizing b1 to be an 8-byte array and padding with zeroes
// 2nd trial:
Int64 lng = BitConverter.ToInt64(b1, 0); // after resizing b1 to be an 8-byte array and padding with zeroes
double d = BitConverter.Int64BitsToDouble(lng);
// 3rd:
float f = BitConverter.ToSingle(b1, 0); // no resizing, just as is 4-bytes
Tried to reverse the bytes order, but still nothing!
These are sample data:
byte b1 = new byte[] {255, 255, 252, 65};
byte b2 = new byte[] {10, 188, 248, 238};
byte b3 = new byte[] {0, 20, 168, 98};
byte b4 = new byte[] {0, 1, 79, 52};
I also still have this Cpp code that is supposed to do the process:
/*
*********************************************************************************
Simple routine to return four bytes from a buffer (MSB ... LSB) as a double, signed value
*/
double get_four_byte_double(unsigned char *b){
double d;
d = (double)(((((((((unsigned int)b[0])&0xFF)<<8) | ((unsigned int)b[1])&0xFF) << 8) | ((unsigned int)b[2])&0xFF) << 8) | ((unsigned int)b[3])&0xFF);
if (d >= max_thirty_two_bit_integer){
d -= thirty_two_bits;
}
d /= 256.0;
//Return the value we have computed
return(d);
}
Help would be highly appreciated.
Edit:
Values of Cpp thirty_two_bits and max_thirty_two_bit_integer:
static double thirty_two_bits = 65536.0 * 65536.0;
static double max_thirty_two_bit_integer = 65536.0 * 65536.0 / 2.0;
Edit (2):
Unfortunately I can not find the actual values for the sample data, but I am sure they are in the range: 0-7000 or 0-15000.

How to clear a bit in a byte?

I need to set and clear some bits in bytes of a byte array.
Set works good but clear doesn't compile (I guess because negation has int as result and it's negative by then and ...).
public const byte BIT_1 = 0x01;
public const byte BIT_2 = 0x02;
byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
// set 1st bit
for (int i = 0; i < bytes.Length; i++)
bytes[i] |= BIT_1;
// clear 2nd bit (set it to 0)
for (int i = 0; i < bytes.Length; i++)
bytes[i] &= (~BIT_2);
How can I clear bits in a byte in a preferably simple way ?
Try this:
int i = 0;
// Set 5th bit
i |= 1 << 5;
Console.WriteLine(i); // 32
// Clear 5th bit
i &= ~(1 << 5);
Console.WriteLine(i); // 0
Version on bytes (and on bytes only in this case):
byte b = 0;
// Set 5th bit
b |= 1 << 5;
Console.WriteLine(b);
// Clear 5th bit
b &= byte.MaxValue ^ (1 << 5);
Console.WriteLine(b);
It appears that you can't do this without converting the byte to an int first.
byte ClearBit(byte b, int i)
{
int x = Convert.ToInt32(b);
x &= ~(1 << i);
return Convert.ToByte(x);
}
This can be avoided by converting to an int and back again:
bytes[i] = (byte)(bytes[i] & ~(BIT_2));
Bitwise operations are not defined on bytes, and using them with bytes will always return an int. So when you use the bitwise NOT on your byte, it will return an int, and as such yield an error when you are trying to AND it with your other byte.
To solve this, you need to explicitely cast the result as a byte again.
byte bit = 0x02;
byte x = 0x0;
// set
x |= bit;
Console.WriteLine(x); // 2
// clear
x &= (byte)~bit;
Console.WriteLine(x); // 0

short to byte conversion

I am trying to convert a short type into 2 bytes type for store in a byte array, here is the snippet thats been working well "so far".
if (type == "short")
{
size = data.size;
databuffer[index+1] = (byte)(data.numeric_data >> 8);
databuffer[index] = (byte)(data.numeric_data & 255);
return size;
}
Numeric_data is int type. It all worked well till i process the value 284 (decimal). It turns out that 284 >> 8 is 1 instead of 4.
The main goal is to have:
byte[0] = 28
byte[1] = 4
Is this what you are looking for:
static void Main(string[] args)
{
short data=284;
byte[] bytes=BitConverter.GetBytes(data);
// bytes[0] = 28
// bytes[1] = 1
}
Just for fun:
public static byte[] ToByteArray(short s)
{
//return, if `short` can be cast to `byte` without overflow
if (s <= byte.MaxValue)
return new byte[] { (byte)s };
List<byte> bytes = new List<byte>();
byte b = 0;
//determine delta through the number of digits
short delta = (short)Math.Pow(10, s.ToString().Length - 3);
//as soon as byte can be not more than 3 digits length
for (int i = 0; i < 3; i++)
{
//take first 3 (or 2, or 1) digits from the high-order digit
short temp = (short)(s / delta);
if (temp > byte.MaxValue) //if it's still too big
delta *= 10;
else //the byte is found, break the loop
{
b = (byte)temp;
break;
}
}
//add the found byte
bytes.Add(b);
//recursively search in the rest of the number
bytes.AddRange(ToByteArray((short)(s % delta)));
return bytes.ToArray();
}
this recursive method does what the OP need with at least any positive short value.
Why would 284 >> 8 would be 4?
Why would 284 be split in two bytes equal to 28 and 4?
The binary representation of 284 is 0000 0001 0001 1100. As you can see, there are two bytes (eight bits) which are 0000 0001 (256 in decimal) and 0001 1100 (28 in decimal).
284 >> 8 is 1 (0000 0001) and it is correct.
284 should be split in two bytes equal to 256 and 24.
You conversion is correct!
If you insist:
short val = 284;
byte a = (byte)(val / 10);
byte b = (byte)(val % 10);
Disclaimer:
This does not make much sense, but it is what you want. I assume you want values from 0 to 99. The logical thing to do would be to use 100 as the denominator and not 10. But then again, I have no idea what you want to do.
Drop the nonsense conversion you are using and go for System.BitConverter.ToInt16
//to bytes
var buffer = System.BitConverter.GetBytes(284); //your short value
//from bytes
var value = System.BitConverter.ToInt16(buffer, 0);

Converting 3 bytes into signed integer in C#

I'm trying to convert 3 bytes to signed integer (Big-endian) in C#.
I've tried to use BitConverter.ToInt32 method, but my problem is what value should have the lats byte.
Can anybody suggest me how can I do it in different way?
I also need to convert 5 (or 6 or 7) bytes to signed long, is there any general rule how to do it?
Thanks in advance for any help.
As a last resort you could always shift+add yourself:
byte b1, b2, b3;
int r = b1 << 16 | b2 << 8 | b3;
Just swap b1/b2/b3 until you have the desired result.
On second thought, this will never produce negative values.
What result do you want when the msb >= 0x80 ?
Part 2, brute force sign extension:
private static int Bytes2Int(byte b1, byte b2, byte b3)
{
int r = 0;
byte b0 = 0xff;
if ((b1 & 0x80) != 0) r |= b0 << 24;
r |= b1 << 16;
r |= b2 << 8;
r |= b3;
return r;
}
I've tested this with:
byte[] bytes = BitConverter.GetBytes(p);
int r = Bytes2Int(bytes[2], bytes[1], bytes[0]);
Console.WriteLine("{0} == {1}", p, r);
for several p.
The last value should be 0 if it isn't set for a positive number, 256 for a negative.
To know what you should pass in, you can try converting it the other way:
var bytes = BitConverter.GetBytes(i);
int x = BitConverter.ToInt32(bytes, 0);
To add to the existing answers here, there's a bit of a gotcha in that Bitconverter.ToInt32() will throw an ArgumentException if the array is less than sizseof(int) (4) bytes in size;
Destination array is not long enough to copy all the items in the collection. Check array index and length.
Given an array less than sizeof(int) (4) bytes in size, you can compensate for left/right padding like so;
Right-pad
Results in positive Int32 numbers
int intByteSize = sizeof(int);
byte[] padded = new byte[intByteSize];
Array.Copy(sourceBytes, 0, padded, 0, sourceBytes.Length);
sourceBytes = padded;
Left-pad
Results in negative Int32 numbers, assuming non-zero value at byte index sourceBytes.Length - 1.
int intByteSize = sizeof(int);
byte[] padded = new byte[intByteSize];
Array.Copy(sourceBytes, 0, padded, intByteSize - sourceBytes.Length, sourceBytes.Length);
sourceBytes = padded;
Once padded, you can safely call int myValue = BitConverter.ToInt32(sourceBytes, 0);.

Categories

Resources