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

My BitArray Class

By , 12 Jun 2006
 

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 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

About the Author

Hamed J.I
Web Developer
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
Member
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.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: Pretty redundant data typememberHamed_ji13 Jun '06 - 8:40 
I don't think it's good to say a class(Any class) can provide every thing, every one need. BitArray class don't provide shifting, convert BitArray to Byte array or other kind of array. and don't provide SubArray from specific bit with specific length.
 
perhaps in transfering data it don't make mistake. you send/recieve BYTES (i don't know what will occur if sender cpu be little-endian and the reciver be big-endian and it's not connect to my article ) and in transfering data we often work on BYTES not BITS. So what's the usage of BitArray class in transfering data ? i don't know if it's usefull. BitArray class is for working with bits so the bit order is important
 
one of the main usage of bitArray class can be encryption/decryption in there bit order is SO IMPORTANT because in encryption/decryption always you need specific bit numbers, changing them, shifting, take apart Bits to two arrays three arrays even more. so you need the functions to what i've mentioned. how you believe it covert all needs ? the main problem is indexer of BitArray class because as i said in storing inverse it. and when you use pointer you get wrong bit.
 
the data come to BitArray class and go. in must of algorithms it don't need to access 100GB of BITS. when you want encrypt/decrypt you only use blocks of your data not all of it(for example in DES encryption algorithm you only work on 64bits of data). as you know we don't save BitArray class as it is. in none encryption/decryption algorithm there no need to all data either. so the memory is not as important as speed.
 
and i think converting in ArrayList take less time than calculating bit numbers and their values
 
Hamed JI
AnswerRe: Pretty redundant data typememberDrazen Dotlic14 Jun '06 - 0:34 
Hamed_ji wrote:
perhaps in transfering data it don't make mistake. you send/recieve BYTES (i don't know what will occur if sender cpu be little-endian and the reciver be big-endian and it's not connect to my article ) and in transfering data we often work on BYTES not BITS. So what's the usage of BitArray class in transfering data ? i don't know if it's usefull. BitArray class is for working with bits so the bit order is important

 
There is no problem when transferring data, because there is network byte order which is fixed and not dependent on the processor's architecture (otherwise communicating between different platforms would be a major PITA).
 
As one of the previous posters mentioned, BitArray is a fine class that works exactly the way you'd expect (assuming you've read the documentation). I've used it in my BitTorrent implementation for the reasons one of the posters mentioned and have not had any problems with it.
 
But that's not the point. Your class is redundant, badly written, slow, and a classic example of "not invented here" syndrome. My advice to you is to embrace and accept the FCL and only write code that deals with your problem space...
 
Bring It On
AnswerRe: Pretty redundant data typememberHamed_ji31 Jul '06 - 12:22 
Our problem here is NOT transferring data via network. i know transferring don't have any problem in bit orders.
 
you give 2 byte (as byte array) to BitArray class first byte is 00000000 and the second is 00000001. WHY when you get item number 9 it's 1 ? is it true order of bits ?
the BitOrder will contain 0000000010000000 IS IT EQUAL TO 0000000000000001 ?
 
if you give integer array to BitArray class it will inverse every 32 bits of order. Is it true Order ?
 
explain me what's the problem here ?. WHY the BitArray class inverse them.
 
let me know how you have used BitArray class in your BitTorrent project.
 
after all as i have said before. it's not slower than BitArray class because it's working with ArrayList and array list as our friend mentioned work with Pointers.
 
and i think a bad class that work true is better than any good class that inverse every 32bit (OR 8 bits) of data
 
i don't know if there's other resource that available about this problem. if it's please let me know them
 
And my advice to you. some times test the problems, find a way to solving them, and then write your message Smile | :)
 
please check example of bit order problem let me know how you solve it.
 
waiting for your answer
 
Hamed JI

AnswerRe: Pretty redundant data typememberDrazen Dotlic31 Jul '06 - 21:20 
Hamed_ji wrote:
you give 2 byte (as byte array) to BitArray class first byte is 00000000 and the second is 00000001. WHY when you get item number 9 it's 1 ? is it true order of bits ?
the BitOrder will contain 0000000010000000 IS IT EQUAL TO 0000000000000001 ?
 
if you give integer array to BitArray class it will inverse every 32 bits of order. Is it true Order ?
 
explain me what's the problem here ?. WHY the BitArray class inverse them.
 
let me know how you have used BitArray class in your BitTorrent project.

 
The reason you are surprised is because you are expecting to see an internal representation of ints (that are storage for the bits in the BitArray internally) the way you would like them to be.
 
But it's just that - internal representation. As we've said numerous times, the only time when you care about that is when you send BitArray over the wire, and in that context everything works fine.
 
There is no inversion. BitArray can store bits any way it likes. It is the class interface that you should use, and I don't see any inconsistencies there.
 
I've used BitArray to track which pieces of the "file" are available at each peer and to track my own too.
 
Hamed_ji wrote:
after all as i have said before. it's not slower than BitArray class because it's working with ArrayList and array list as our friend mentioned work with Pointers.
 
and i think a bad class that work true is better than any good class that inverse every 32bit (OR 8 bits) of data
 
i don't know if there's other resource that available about this problem. if it's please let me know them
 
And my advice to you. some times test the problems, find a way to solving them, and then write your message

 
It is slower. There are no pointers involved. There is boxing. All of this has been stated before. Have you checked if any of these claims is true?
 
Bad class is just bad. It does not matter if it "works", because in that sense BitArray works too. There is no problem.
 
If you still think this makes no sense, I have nothing more to add. Just check the MSDN documentation on all the points given above (especially by Aleksey).
 
Bring It On

GeneralRe: Pretty redundant data typememberHamed_ji31 Jul '06 - 23:22 
imagine we have a long value as 4 byte array or long array (for biggers) give it to BitArray class. even without any changes we want to save it. how you will save it ? inversing every 8 bits ?
 
what you give and what you take is completly diffrent. if it's true to give number to each bit from right, it must give number from right must bit not only for every 8 bits. this kind of Bit order is not what I need.
 
about the pointers. you didn't read previous messages. as my dear friend "Alexey A. Popov" have mentioned, the ArrayList class works with POINTERS and not copying data. you can test it. so it work with pointers
 
i remind you, didn't solve the problem i have mentioned. if BitArray work true please solve that
 
Hamed JI

GeneralRe: Pretty redundant data typememberAlexey A. Popov14 Jun '06 - 6:25 
OK, let me answer step by step.
First, when you say that a class cannot provide everything you need, I agree. If we had a class that provided everything we would be out of this busyness Smile | :) However, a class is either a unit (like the System.String) or a template (being it a generic, abstract or just a class with virtual functions). The unit cannot and should not be extended/changed/tampered with, only used. That's why strings (and bit arrays) are sealed.
Second, when you say that BitArray cannot be converted to and from any kind of array, you're wrong. Just take a look at the documentation, CopyTo method and three constructors do just that. However, you are correct when saying that the BitArray does not support bit shifting. This is bad. But BitArray is not a kind of integer (and shfts are applicable to binary integers), it's just a bit map, an array of flags. And BitArray works perfectly for it's purpose.
Third, as far as I remember, endianness does not affect order of bits in a byte, there's no htob/btoh functions and IPAddredd declares HostToNetworkOrder/NetworkToHostOrder only for shorts/ints/longs. So sending BitArrays over the wire as an array of bytes is not an issue. Why am I talking about it then? Because it the only place where you need to bypass the BitArray's interface and get a hand on the raw data.
Fourth, you're correct that there's no SubArray method for the BitArray. Frankly, I've never needed one, but on this I agree, it's better to have this method. Again, you can easyly emulate this method either by copying a range of bits bit by bit or by converting the BitArray to an array of booleans, extracting the required range with Array.Copy and creating a new BitArray. In .Net 3.0 you'll be able to create a kinda mixin with that functionality for the BitArray.
Fifth, when working with the BitArray you don't have to worry about the order of bits, use indexer and forget about pointers (I shudder) because we are in the world of CLR, far away from C/C++, and there's Smalltalk shining above the horizon.
Sixth, when you work with encription, you do need big integers, but not only for logical operators and bit shifts but also for calculations. The BitArray cannot perform arithmetics, that's the fact of life. There are plenty of implementations for big integers, you can find at least two here, on the CodeProject, and one in the CLR extensions for Java/J#.
And seventh, boxing/unboxing of booleans might be good or acceptable in test applications. In a real-world applicaton heavy boxing would hit GC hard eliminating all advantages of ArrayList.

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

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