Having a Little “Bit” of Fun with C#
Recently in the forum someone asked about bits in a byte and how it is populated into a bit array
The thread originator first populated a byte array and fed that into a bit array…
byte [] byteArray = new byte[] { 1 };
BitArray bitArray = new BitArray(byteArray);
When he went to print the array to his surprise the output was backward to what he expected…
//Simplification of what he did is this
for (int i = 0; i < bitArray.Length; i++)
{
Console.Write(Convert.ToInt16(bitArray[i]));
//note: without the convert to an int the output would be true and false
//10000000 would output truefalsefalsefalsefalsefalsefalse
}
He should have done something like this starting with the most significant bit
for (var idx = bitArray.Length - 1; idx >= 0; idx--) //Parse from left most bit to right most bit
{
Console.Write("{0}", Convert.ToInt16(bitArray[idx]));
}
Console.WriteLine();
//note: without the convert to an int the output would be true and false
//00000001 would output falsefalsefalsefalsefalsefalsefalsetrue
Let’s explore why… here is a byte represented by a string of bits (00000001)
When a byte is converted to a bit array it starts with position 0 and goes up to 7. The bit positions represent values and adding all the positions set to 1 or true totals the value of the converted byte. A byte starts with the lowest significant bit on the right and the most significant bit on the left
So what does all this mean?
The logic of a byte is each position represents a value the lowest or least significant bit represents 1, the next bit or next one to the left of it is 2, the next 4 and so on…
Bit position 7 6 5 4 3 2 1 0
Value of position 128 64 32 16 8 4 2 1
Let’s see what some strings of eight bits or a byte equals
Here we have just the first or lowest significant bit set to true or 1 which also represent the value 1, all others unset
00000001 = 1 // 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1
Here we have the least significant bit set, the next one unset and the next following one set… all others unset
00000101 = 5 // 0 + 0 + 0 + 0 + 0 + 0 + 4 + 1
Here we have another… see what it is…
10001001 = 137 // 128 + 0 + 0 + 0 + 8 + 0 + 0 + 1
Going beyond the context of the forum post we are now going to talk about bitwise operations
AND ( & sign in C#, And in vb.nET )
OR (Inclusive OR) ( | sign in C#, Or in vb.nET )
NOT ( ~ sign in C#, Not in vb.nET)
XOR (Exclusive OR) ( ^ sign in C#, Xor in vb.nET)
Left Shift ( << sign in C# and vb.nET)
Right Shift ( >> sign in C# and vb.nET)
And finally build on shift with an example of Circular ***
The AND ( & sign in C#, And in vb.nET ) will take the corresponding placed bits and compare them and output according the following logic table
A helper method providing AND functionality to a pair of bytes
private static byte ByteAND(byte val1, byte val2)
{
return Convert.ToByte(val1 & val2);
}
//use it as follows
byte andVal1 = 6; //00000110
byte andVal2 = 5; //00000101
byte outputAND = ByteAND(andVal1, andVal2);
//returns 4 or 00000100
The OR (Inclusive OR) ( | sign in C#, Or in VB.NET ) will take the corresponding placed bits and compare them and output according to the following logic table
A helper method providing OR functionality to a pair of bytes
private static byte ByteOR(byte val1, byte val2)
{
return Convert.ToByte(val1 | val2);
}
//use as follows
byte orVal1 = 6; //00000110
byte orVal2 = 5; //00000101
byte outputOR = ByteOR(orVal1, orVal2);
//retuturns 7 or 00000111
The NOT ( ~ sign in C#, Not in VB.NET) ) will take the corresponding placed bits and compare them and output according to the following logic table
A helper method providing NOT functionality to a pair of bytes
private static byte ByteNOT(byte val1)
{
return (byte)~val1;
}
//use as follows
byte notVal1 = 1; //00000001
byte outputNOT = ByteNOT(notVal1);
//returns 254 or 11111110
The XOR (Exclusive OR) ( ^ sign in C#, Xor in VB.NET) will take the corresponding placed bits and compare them and output according to the following logic table
A helper method providing NOT functionality to a pair of bytes
private static byte ByteXOR(byte val1, byte val2)
{
return Convert.ToByte(val1 ^ val2);
}
//use as follows
byte xorVal1 = 6; //00000110
byte xorVal2 = 5; //00000101
byte outputXOR = ByteXOR(xorVal1, xorVal2);
//returns 3 or 00000011
Note: In the following if you click the images you will see the animation
Next are shift operations
Left Shift to shift all bits to the left a specified number of times
private static byte ShiftLeft(byte val1, int shift)
{
return (byte)(val1 << shift);
}
//use as follows
byte leftVal = 1;
byte outputLeftShift = ShiftLeft(leftVal, 1); //Shift one bit to left
//returns 2 or 00000010
**Right Shift to shift all bits to the left a specified number of times
private static byte ShiftRight(byte val1, int shift)
{
return (byte)(val1 >> shift); //or val1 << (8 - shift));
}
//use as follows
byte rightVal = 2;
byte outputRightShift = ShiftRight(rightVal, 1); //Shift one bit to right
//returns 1 or 00000001
**Now we are going to create a circular shift method and note C# doesn’t include a built in operator for this… We are going to create a method that does both right and left **
private static byte CircularShift(byte val, int shift, bool rightLeft)
{
byte newVal = 0;
if (rightLeft)
{
//Shift right
newVal = (byte)(val >> shift | val << (8 - shift));
}
else if (!rightLeft)
{
//Shift left
newVal = (byte)(val << shift | val >> (8 - shift));
}
return newVal;
}
//use as follows
byte circRightVal = 1; //00000001
byte outputCircRight = CircularShift(circRightVal, 1, true);
//returns 128 or 10000000
byte circLeftVal = 128; //10000000
byte outputCircLeft = CircularShift(circLeftVal, 1, false);
//returns 1 or 00000001