Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / June 2005

Tip: Looking for answers? Try searching our database.

bit shifting

Thread view: 
Michael Powe - 11 Jun 2005 18:10 GMT
Hello,

I'm trying to get some better understanding of bit shifting.  I found
a method on the net that prints out the bits of an arbitrary
character, number, &c.  I've played with it but I'm just not getting
it.

Here it is:

public void printBits(int number, int startBit, int numBits)
   {
       int bitmask;
       bitmask = 0x80000000 >>> startBit;
       numBits += startBit;
       for(int i=startBit; i < numBits; ++i)
       {
           if((number & bitmask) == 0)
               System.out.print('0');
           else
               System.out.print('1');
           bitmask >>>= 1;
       }
       System.out.println();
   }

Here's some questions I have:

In the examples of usage, startBit always == 24 and numBits == 8.
This, of course, makes 32 bits.  But, why start at 24?

What if I wanted to display the bits in a long or a double?

What is the significance of setting the bitmask with 0x80000000?

Thanks for the help.  I know this is probably knowledge I never will
use, but I just would like to grasp how this stuff works.

mp

Signature

Michael Powe        michael@trollope.org        Naugatuck CT USA
"It stands to reason that self-righteous, inflexible, single-minded,
authoritarian true believers are politically organized. Open-minded,
flexible, complex, ambiguous, anti-authoritarian people would just as
soon be left to mind their own f.cking business." - R.U. Sirius

ninja java - 11 Jun 2005 19:21 GMT
A while ago I created a Base64 encoder/decoder, which required the use
of bit shifting.
However I had trouble with the shift operators.
So instead I created methods to unsign a byte and the shift the bits
left or right.

public int unsign(int b) {
   if (b < 0) {
       return b - Byte.MIN_VALUE*2;
   } else {
       return b;
   }
}//This method is designed to unsign byte values.

public int shiftRight(int b, int n) {
   return (int) (b / Math.pow(2, n));
}

public int shiftLeft(int b, int n) throws IOException {
   return (int) (b * Math.pow(2, n));
}

//I think I had trouble because there is no unsigned left shift
operator (<<<) similar to >>>.

0x80000000 = 10000000000000000000000000000000 in binary.
That means that as bitmask >>>= 1 goes there is one less zero in the
binary number.

Thus number & bitmask will, assuming number equals 10010 in binary and
bitmask equals 10000 in binary, give this result
/* ~ is approximately*/
                                                      //giving out put
of
i ~= 0; number & bitmask = 10000  //bitmask = 10000    1
i ~= 1; number & bitmask = 0      //bitmask = 1000     0
i ~= 2; number & bitmask = 0      //bitmask = 100      0
i ~= 3; number & bitmask = 10     //bitmask = 10       1
i ~= 4; number & bitmask = 0      //bitmask = 1        0

Simple "bitwise and" logic (& operator).

//Quite frankly
numBits += startBit;
       for(int i=startBit; i < numBits; ++i)
//is overly complicated; it is much easier to read as
for (int i = 0; i < numBits; ++i)
//numBits += startBit; has no real usage.

0x80000000 is essentially 10000000000000000000000000000000 in binary.
and if you notice 10000000000000000000000000000000 is 32 characters
long, this to me would indicate that 0x80000000 is the maximum value of
an int value, since int's are 32 bits.

//note that (int) 0xFFFFFFFF = -1; due to int's being signed values;
//(int) 0x80000001 = Integer.MIN_VALUE;
//(int) 0x80000000 = Integer.MAX_VALUE;

Because of that, this method can only work on int values.
So in order to change

public void printBits(int number, int startBit, int numBits)
//into
public void printBits(long number, int startBit, int numBits)

all you need to do is change 0x80000000 to 0x8000000000000000L
//note the L at the end is used to prevent a compiler error.

and of course all you have to do then is change
int bitmask;
into
long bitmask;

As for
"In the examples of usage, startBit always == 24 and numBits == 8.
This, of course, makes 32 bits.  But, why start at 24? "

That depends entirely on the example usage.

On a side note; Since numBits = 8 that would actually print out 8
characters (bits) to the console.  However it is true that since
"number" is an int in
//public void printBits(int number...) {...}
that number is 32 bits.

"What if I wanted to display the bits in a long or a double?"

Well I showed you how to do a long, but I don't know off the top of my
head how to do a double.  Hopefully it is basically the same as
changing int to a long by using a different starting bitmask.

"Thanks for the help.  I know this is probably knowledge I never will
use, but I just would like to grasp how this stuff works. "

Not if you ever have to work with encoding Base64! (see top of post)

//Hope that helps.
Remi Arntzen - 12 Jun 2005 03:16 GMT
OPPPS!
0x7FFFFFFF is Integer.MAX_VALUE
and 0x80000000 is simply used to get the int value with only the
highest order bit set.
and 0x80000000 is Integer.MIN_VALUE
//only off by one :-)

every thing else should be the same

/* **CORRECTED COPY***/
A while ago I created a Base64 encoder/decoder, which required the use
of bit shifting.
However I had trouble with the shift operators.
So instead I created methods to unsign a byte and the shift the bits
left or right.

public int unsign(int b) {
   if (b < 0) {
       return b - Byte.MIN_VALUE*2;
   } else {
       return b;
   }

}//This method is designed to unsign byte values.

public int shiftRight(int b, int n) {
   return (int) (b / Math.pow(2, n));

}

public int shiftLeft(int b, int n) throws IOException {
   return (int) (b * Math.pow(2, n));

}

//I think I had trouble because there is no unsigned left shift
operator (<<<) similar to >>>.

0x80000000 = 10000000000000000000000000000000 in binary.
That means that as bitmask >>>= 1 goes there is one less zero in the
binary number.  0x80000000 is used simply to get the int value with
only its highest order bit set.

//note that (int) 0xFFFFFFFF = -1; due to int's being signed values;
//(int) 0x7FFFFFFF = Integer.MAX_VALUE;
//(int) 0x80000000 = Integer.MIN_VALUE;

Thus (number & bitmask) will, assuming number equals 10010 in binary
and
bitmask equals 10000 in binary, give this result
/* ~ is approximately*/

                        //giving out put of
i ~= 0; number & bitmask = 10000 //bitmask = 10000     1
i ~= 1; number & bitmask = 0          //bitmask = 1000        0
i ~= 2; number & bitmask = 0          //bitmask = 100          0
i ~= 3; number & bitmask = 10        //bitmask = 10            1
i ~= 4; number & bitmask = 0          //bitmask = 1               0

Simple "bitwise and" logic (& operator).

//Quite frankly
numBits += startBit;
for(int i=startBit; i < numBits; ++i)
//is overly complicated, and is much easier to read as
for (int i = 0; i < numBits; ++i)
//numBits += startBit; has no real usage.

Because of the bitmask, this method can only work on int values.
So in order to change

public void printBits(int number, int startBit, int numBits)
//into
public void printBits(long number, int startBit, int numBits)

all you need to do is change 0x80000000 to 0x8000000000000000L
//note the L at the end is used to prevent a compiler error.

and of course all you have to do then is change
int bitmask;
into
long bitmask;

As for
"
In the examples of usage, startBit always == 24 and numBits == 8.
This, of course, makes 32 bits.  But, why start at 24

? "

That depends entirely on the example usage.

On a side note; Since numBits = 8 that would actually print out 8
characters (bits) to the console.  However it is true that since
"number" is an int in
//public void printBits(int number...) {...}
that number is 32 bits.

"
What if I wanted to display the bits in a long or a double

?"

Well I showed you how to do a long, but I don't know off the top of my
head how to do a double.  Hopefully it is basically the same as
changing int to a long by using a different starting bitmask.

//Hope that helps.
/* **CORRECTED COPY***/
Michael Powe - 12 Jun 2005 22:40 GMT
>>>>> "ninja" == ninja java <Remi.Arntzen@gmail.com> writes:

   ninja> A while ago I created a Base64 encoder/decoder, which
   ninja> required the use of bit shifting.  However I had trouble
   ninja> with the shift operators.  So instead I created methods to
   ninja> unsign a byte and the shift the bits left or right.

       [ ... ]

Your explanations really help.  Thank you.  I'm working on it now.  I
really appreciate your taking the time to explain this.

mp

Signature

Michael Powe        michael@trollope.org        Naugatuck CT USA
"In every country and in every age, the priest has been hostile to
liberty.  He is always in alliance with the despot, abetting his
abuses in return for protection to his own." -- Thomas Jefferson to
Horatio G. Spafford, 1814. ME 14:119



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.