Click here to Skip to main content
Click here to Skip to main content

My BitArray Class

, 12 Jun 2006
Rate this:
Please Sign up or sign in to vote.
A BitArray class with more function

Introduction

There's a BitArray class in namespace System.Collections.BitArray. But there's a big problem in it.

if you define two bytes as:

byte[] bits = new byte[2];
bits[0] = 1;
bits[1] = 3;

And use them in constructor of BitArray class, the bits must be "0000000100000011" because the byte[0] is "00000001"(binary view of 1) and the byte[1] is "00000011"(binary view of 3). Constructor first must use the first byte and then use the second byte.

But it won't !

The bits in the BitArray class will be "100000001100000". as you can see, the constructor first inverse each byte and then use it. and if you inverse all bits you gain "0000001100000001" wich that's not what we want.

Why ?

As i understood the problem come from CPU ! i wrote a thread in MSDN forum <!-- Article Starts - DO NOT ADD HTML/BODY START TAGS-->http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=466424&SiteID=1. i understood most of our cpu works little-endian (thank's nobugz in MSDN forum) it means they inverse bits.

for example if you send "00000001" to cpu it will store it in ram as "10000000" and when you read it cpu inverse it again and show you "00000001".

so our problem occur when we send "00000001" to cpu, cpu store it in ram as "10000000" and when we want the first bit the cpu return "1".

i think this problem occur in the constructor of System.Collections.BitArray. BitArray class must define a pointer to the first bit of array and start reading bits from there.

The program below show the problem. first it store 1 and 3 in two bytes. then use byte array for constructor. and show you a messagebox contain bits. it's not bad to change byte to int and 16 to 64 to see how problem will change. the constructor will inverse every 32 bits of data (int length)

byte[] bits = new byte[2];
bits[0] = 1;
bits[1] = 3;
BitArray BA = new BitArray(bits);
string st = string.Empty;
for(int i=0; i< 16; i++)
  st += Convert.ToInt16(BA.Get(i)).ToString();
MessageBox.Show(st); //source don't contain this test program

My BitArray Class

So i started to write my own bit array class. not even solve this problem also add more functions to it.

Inheritance Problem

First i want to write class that inherits from System.Collections.BitArray. but i don't know why microsoft defined BitArray class as a Sealed( notInheritable) class.

So i declared a ArrayList and store my bits in it. i have tried to my class be similar to BitArray class.

How it work's

I show an example of how my constructor work's for a byte array as an argument:

for each byte in array use Convert.ToString(TheByte,2). this function convert the byte to binary string. if our first byte be 43 this function return "101011". as you can see it's only 6 bit length. for store in our array a byte must be 8 bits length. so we call FixLength function to solve length problem. FixLength add two zero at the begining. and return "00101011"

Now we can add "00101011" to our array. we do this by calling AddBits function. this function add "false" to arrayList for each 0 and add "true" to arrayList for each 1 

public JIBitArray(byte[] bits)
{
  string st;
  foreach(byte b in bits)
  {
    st = FixLength(Convert.ToString(b,2),8);
    AddBits(st);
  }
}
private string FixLength(string num,int length)
{
  while(num.Length < length)
    num = num.Insert(0,"0");
  return num;
}<FONT size=2>
private void AddBits(string bits)
{
  foreach(char ch in bits)
  {
    if(ch == '0')
      _Bits.Add(false);
    else if(ch == '1')
      _Bits.Add(true);
    else
      throw(new ArgumentException("bits Contain none 0 1 character"));
  }
}<FONT size=2>

we do the same for other constructors.

Functions

i have defined Get, Set, SetAll, Count, Or, Xor, And, Not functions to do the same as Microsoft BitArray class do

And add more functions:

1. ShiftLeft, ShiftRight for shifting bits to left or right

To shift left simply remove bits from left and then add 0 bits to the end

2. GetLong, GetInt, GetByte, GetShort

This functions use to convert our bits to Long Array, Int Array Byte Array and Short Array

I explain one of them:

GetByte

we need to calculate return array length. To do this:

int</FONT> ArrayBound = (int)Math.Ceiling((double)this._Bits.Count/8);

Then declare array for returning:

byte[] Bits = new byte[ArrayBound];

if out array lenght be 9 bits. we need to return byte array with length of 2. so the array bound will be 2 and it means the lenght of array must be 16 bits. for fixing the length of our array we declare Temp JIBitArray and Fix it length to ArrayBound * ByteLength(which is 8)

JIBitArray Temp = new JIBitArray();
Temp._Bits = this._Bits;
Temp = FixLength(Temp,ArrayBound * 8);

Convert each 8 bits block to a byte by using "Convert.ToByte(string,base)" function.

<FONT color=#0000ff size=2><P>for</FONT><FONT size=2>(</FONT><FONT color=#0000ff size=2>int</FONT><FONT size=2> i=0; i< Temp._Bits.Count; i += 8)</P><P>{</P><P>  Bits[i/8] = Convert.ToByte(Temp.SubJIBitArray(i,8).ToString(),2);</P><P>}</P></FONT>

And then return bits.

3. RemoveBeginingZeros

if you have JIBitArray contain "00001110101" RemoveBeginingZeros return "110101"

4. operators

i have declared operator functions for this class

& And, | Or, ^ Xor, >> ShiftRight, << ShiftLeft

5. SubJIBitArray

it works like SubString function for string class. SubJIBitArray(2,3) for "0110110101" return "101"

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Hamed J.I
Web Developer
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
I began programming with C/C++ when i was 15. Then try to learn VC++ but at the middle of my reading .NET came.
 
I began to read C# and VB.NET and also began designing basic websites by FrontPage and developed some websites for our school and some other companis.
 
Later learn Microcontroller and design some digital circuits with PIC microcontrollers for a industrial controller company.
 
As I learned SQL and ASP.NET developed some website such as news portals that are active now.
 
Now i'm a software student and teach programming in computer institues. And have my own job by getting projects from companies.

Comments and Discussions

 
GeneralProblem with And method PinmemberMember 187509017-Mar-08 4:00 
Generalslow performance PinmemberZronZ7-Jan-07 23:08 
GeneralRe: slow performance [modified] Pinmemberyianfang28-Aug-07 16:51 
NewsThis guy saved my job!!!!! PinmemberPeace2u20-Jun-06 21:44 
GeneralRe: This guy saved my job!!!!! PinmemberHamed_ji31-Jul-06 13:24 
GeneralPretty redundant data type PinmemberAlexey A. Popov13-Jun-06 1:47 
GeneralRe: Pretty redundant data type PinmemberHamed_ji13-Jun-06 6:18 
GeneralRe: Pretty redundant data type Pinmemberreflex@codeproject13-Jun-06 7:10 
GeneralRe: Pretty redundant data type PinmemberHamed_ji13-Jun-06 8:51 
GeneralRe: Pretty redundant data type PinmemberAlexey A. Popov13-Jun-06 8:33 
Dont't get it too personal!
The BCL provides a lot of high-level, self-contained classes. All value types, strings. And BitArray. You cannot inherit it because it provides everything you need. Except, of course, access to the bits themselves.
Consider this class a black box. You know if you set the bit with index 3 to true, you're gonna get true when getting the bit's number 3 value. A developer should not care how the bits are stored inside (in 32 bit words, actually). All they need is the indexer.
As for CopyTo/constructors. For instance, you want to transfer a BitArray over the wire (BTW, BitTorrent does almost it). You can a) serialize it to a memory stream, convert the stream to a byte array and send it; the receiver would reconstruct the memory stream and deserialize the BitArray; b) allocate array, use CopyTo to fill it, send over the wire, create a new BitArray based on the bytes. The second case is a bit more effective. But! But you should not rely on how bits really ordered. Noone would play with serialized objects.
As for keeping bool values in an ArrayList. I think you're right in some cases you might gain some performance. But from the memory POV it's horrible. ArrayList in .Net 1.x stores reference objects. If you keep bools in it, it would box/unbox them, converting from a value object (System.Boolean) to a reference in the indexer's getter and back in the setter. The heap would be cluttered with a lot of small short living objects. The BitArray keeps values in a contineous block of memory, packing/unpacking bits in the indexer. I.e. it converts a value object (the integer value used as bit storage) to a value object (a bool value) which is more effective in a real-world application. It is true that .Net 2.0 generics help you to avoid boxing, but in this case you're wasting 8 times more memory anyway.
My main point is - one doesn't have to know how exactly the BitArray keeps the bits and one should not rely on the processor's architecture by tweaking bits directly. We are programming C#/CLR, not C/Unix.
GeneralRe: Pretty redundant data type PinmemberHamed_ji13-Jun-06 9:40 
AnswerRe: Pretty redundant data type PinmemberDrazen Dotlic14-Jun-06 1:34 
AnswerRe: Pretty redundant data type PinmemberHamed_ji31-Jul-06 13:22 
AnswerRe: Pretty redundant data type PinmemberDrazen Dotlic31-Jul-06 22:20 
GeneralRe: Pretty redundant data type PinmemberHamed_ji1-Aug-06 0:22 
GeneralRe: Pretty redundant data type PinmemberAlexey A. Popov14-Jun-06 7:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141220.1 | Last Updated 13 Jun 2006
Article Copyright 2006 by Hamed J.I
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid