Share via


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

http://social.msdn.microsoft.com/Forums/vstudio/en-US/6c3fe986-d347-44e9-b310-cae9c25f1d9d/about-bytes-and-bits

 
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