Confused About Bit Shifting (Counting Bits in Byte) - java

I'm trying to count the number of set bits in a byte but I appear to be running into some issues I can't find answers to.
My code currently looks like
public static int numBits(byte input){
int count = 0;
while (input != 0){
if ((input & 1)==1){
count++;
}
input >>= 1;
}
return count;
}
It appeared to work fine until I tried x = -1.
This ended up creating an infinite loop as value 1 bits were being inserted. So I stumbled upon
Java: right shift on negative number
which to my interpretation meant I should use input >>>= 1; but this still led to an infinite loop.
So I tried to figure out what was going on by trying
byte x = -1;
System.out.println(x >>> 1);
System.out.println(x >> 1);
which lead to
2147483647
-1
leaving me more confused. Where did the number 2147483647 come from and where might I be making a logic mistake?

The >>> operator means shift to the right, but do not sign-extend.
Your trial is pretty close, but you're not actually modifying x, so you can do:
int x = -1;
x = x >>> 1;
System.out.println(x);
x = x >> 1; // highest bit = 0 now
System.out.println(x);
Which will yield
2147483647
1073741823
Notice that I'm using int rather than byte here, since the result of bit shifts coerces the input to at least be integer sized.
Interestingly, when you run:
byte input = -1;
input = (byte) (input >>> 1);
The result is still -1. This is because of the type coercion happening with this operator mentioned above. To prevent this from affecting you, you can mask the bits of input to make sure you only take the first 8:
byte input = -1;
input = (byte) ((input & 0xFF) >>> 1);
Putting this together, if you were to run:
byte input = -1;
input = (byte) ((input & 0xFF) >>> 1);
System.out.println(input);
input = (byte) ((input & 0xFF) >> 1);
System.out.println(input);
You get the expected results:
127
63

This is all being caused by the way signed integers are stored as binary values. The way the highest bit of the number determines the sign (sort of—zero makes things weird), and the sign was being preserved with the arithmetic shift. Your print statements are giving weird results because the results are being promoted to int values instead of bytes.
If you want a really simple fix for this, you can just use an int to store your value, but make sure to mask off everything but the lowest-order byte:
public static int numBits(byte inByte){
int count = 0;
int input = inByte & 0xFF;
while (input != 0){
if ((input & 1)==1){
count++;
}
input >>= 1;
}
return count;
}
Like I said in my comment above, you should really read about Two's complement representation of signed numbers in binary. If you understand how negative numbers are represented, and the difference between arithmetic/logical shifts, all of that will make perfect sense.

You might find how the JVM actually does it is interesting. Note: there is only 8 bits so you don't really need a loop.
public static int bitCount(int i) {
// HD, Figure 5-2
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
}
NOTE: On the x86/x64, the JVM replaces this with an intrinsic. i.e. it uses a single machine code instruction. If you copy this method and compare it will calling the original it is 3x slower as the JVM only replaces a hard coded list of methods, so it will replace Integer.bitCOunt, but not a copy.
In short, use the built in method instead of re-inventing it.

Related

I am trying to depict what this java print statement “ (((0xFF << (i * 8)) & test)))) “ means

My assignment is to figure out what this java program written by my teacher is doing, without running it. I have attached the whole (short) program and bolded the expression I do not understand. It is apart of the first for loop, which I am also a little unclear as to what it does.
import java.util.*;
int intSize = Integer.SIZE / 8; char storage[] = new char[intSize]; int test = 0xffffffff,
test2 = 0;
System.out.println(String.format("0x%08x",0xFF << (3 * 8) & test));
storage[0] = (char) ((0xF << 4));
for (int i = intSize - 1 ; i > -1 ; i--)
// storage[i] = (char) ((0xFF << (i * 8)) & test);
System.out.println(String.format("0x%08x",**(((0xFF << (i * 8)) & test))));**
for (int i = 0, j = intSize-1; i < intSize ; i++, j--)
test2 &= (((int) storage[i]) << (j * 8));
System.out.println(“The Magic Word of the Day is the English word for: ”+test2);
A useful way to analyze what code is doing, is to break it down into the smallest possible steps.
First, there are extra parentheses which are not needed. So let’s clean that up, by changing this:
(((0xFF << (i * 8)) & test))
to this, which is exactly the same thing:
(0xFF << (i * 8)) & test
Now, imagine it broken down into separate steps:
int value = i * 8;
int mask = 0xFF << value;
int result = mask & test;
So, you know that:
value is a multiple of 8
mask is eight contiguous 1 bits (because 0xFF is 11111111 in base two), shifted by a count which is a multiple of 8
result is the application of that mask to the 32 bits 11111111111111111111111111111111 (which is the base two form of 0xffffffff, which is the value of test)
Hopefully, if you’ve been given this assignment, you already understand the purpose of the bitwise & operator: each 1-bit in one operand preserves the corresponding bit in the other operand, while 0-bits in either operand are always cleared in the result.
There a lot of things in this code which are poor practice. Not challenging, just bad. You’ve been given an assignment which is much harder than it should be, in my opinion, for the purpose of demonstrating knowledge of Java’s mathematical and bitwise operators.

Get bits of a given range more effective?

It's been a while, that I did bit manipulations and I'm not sure if this can be done in a more effective way.
What I want is to get bits of a specific range from a value.
Let's say the binary of the value is: 0b1101101
Now I want to get a 4-bit range from the 2nd to the 5th bit of this value in it's two's complement.
The range I wanna get: 0b1011
Value in Two's complement: -5
This is the code I have, with some thoughts what I'm doing:
public int bitRange(int value, int from, int to) {
// cut the least significant bits
value = value >> from;
// create the mask
int mask = 0;
for (int i = from; i <= to; i++) {
mask = (mask << 1) + 1;
}
// extract the bits
value = value & mask;
// needed to check the MSB of the range
int msb = 1 << (to - from);
// if MSB is 1, XOR and inverse it
if ((value & msb) == msb ) {
value = value ^ mask;
value = ~value;
}
return value;
}
Now I would like to know if this can be done more effective? Especially the creation of the dynamic mask and the check of the MSB of the range, to be able to convert the bit range. Another point is, as user3344003 pointed out correctly, if the range would be 1 bit, the output would be -1. I'm sure there is a possible improvement.
For your mask, you could go something like
int mask = 0xffffffff >> 32-(to-from);
Though the chance of that exact code being correct is small. Probably off by one, edge issues, sign problems. But it's on the right track?
Here's your mask:
int mask = 0xffffffff >>> 32 - (to - from + 1);
You have to use >>> due to sign bit is 1.
Another solution could be to store the possible masks which can be 31 values at the most:
private static int[] MASKS = new int[31];
static {
MASKS[0] = 1;
for (int i = 1; i < MASKS.length; i++)
MASKS[i] = (MASKS[i - 1] << 1) + 1;
}
And using this your mask:
int mask = MASKS[to - from];
You can do the same for the msb mask, just store the possible values in a static array, and you don't have to calculate it in your method.
Disclaimer: I'm more of a C or C++ programmer, and I know there are some subtles between the bitwise operators in the different languages. But it seems to me that this can be done in one line as follows by taking advantage of the arithmetic shift that will result when shifting a negative value to the right, where one's will be shifted in for the sign extension.
public int bitRange(int value, int from, int to) {
int waste = 31 - to;
return (value << waste) >> (waste + from);
}
breakdown:
int a = 31 - to; // the number of bits to throw away on the left
int b = value << a; // shift the bits to throw away off the left of the value
int c = a + from; // the number of bits that now need to be thrown away on the right
int d = b >> c; // throw bits away on the right, and extend the sign on the left
return d;

Removing bit at specific index

I'm basically trying to remove a bit from an integer at a specific index. That is, I do not want to unset/clear the bit; I actually want to strip it, so that every higher bit moves down, replacing the respective bit at its position. Visually, this could be compared to deleting an element from an array or removing a character from a string.
For the sake of clarity, some examples:
1011011 (original number)
^ index = 2
0101111 (result)
10000000000000000000000000000001
^ index = 31
00000000000000000000000000000001
1111111111111111111111111111110
^ index = 0
0111111111111111111111111111111
Full of confidence, I started shifting some bits, and came up with the following Java method...
public static int removeBit(int num, int i) {
int out = (num >>> (i + 1)) << i;
out |= (num << (32 - i)) >>> (32 - i);
return out;
}
... which almost always works, except for some extreme cases:
10000000000000000000000000000001 (= Integer.MAX_VALUE - 1)
^ index = 31, results in:
10000000000000000000000000000001
1011011
^ index = 0, results in:
1111111
In other words, if the index is 0 or 31 (least or most significant bit), my method will output garbage.
I can't seem to wrap my head around it, and that's why I'm asking: How can I remove an arbitrary bit in a 32-bit integer?
I'm especially looking for the most performant way to do it in Java (smallest possible memory and CPU consumption), since this operation has to run at least a couple million times. That's why something like "convert it into a string, remove the char and convert it back" is out of the question.
As explained in the comments, the shift counts rolled over to >= 32, which caused trouble.
Anyway, let's derive a way to do it.
Start by considering the two "pieces", the low piece (which gets copied in its original position and may be anywhere between 0 .. 31 bits long) and the high piece (which gets shifted down by one, and can also be between 0 .. 31 bits long). The total length of the pieces is always 31.
The mask for the low piece is obvious: ~(-1 << i)
Which makes the mask for the high piece obvious: ~lowmask << 1. The high piece is shifted anyway, so that shift can go.
Now all that's left is to take the pieces and OR them together, and you would get
static int removeBit(int x, int i)
{
int mask = ~(-1 << i);
return (x & mask) | ((x >>> 1) & ~mask);
}
Throw out the double negation:
static int removeBit(int x, int i)
{
int mask = -1 << i;
return (x & ~mask) | ((x >>> 1) & mask);
}
Just mask out the bits needed, no need to shift back and forth
public static int removeBit(int num, int index) {
int mask = (1 << index) - 1;
return ((num & ((~mask) << 1)) >>> 1) | (num & mask);
}
or
public static int removeBit(int num, int index) {
int mask = (1 << index) - 1;
return ((num >>> 1) & ~mask) | (num & mask);
}
Some platforms have very efficient parallel bit extract so if you can do the job in JNI or if Java has some intrinsic similar to Bmi2.ParallelBitExtract then you can do like this
public static int removeBit(int num, int index) {
return Bmi2.ParallelBitExtract(num, ~(1 << index));
}
If it is important to use the minimum number of instructions, for these kind of bit shuffling it is often best to calculate the bits that need to be toggled and then use xor to apply that. Also here this saves one instruction compared to harold's solution:
static int removeBit(int x, int i)
{
int mask = -1 << i;
return ((x ^ (x >>> 1)) & mask) ^ x;
}
or
static int removeBit(int x, int i)
{
return (((x ^ (x >>> 1)) >>> i) << i) ^ x;
}

How to find most significant bit (MSB)

I want to know which value the first bit of a byte has.
For example:
I have byte m = (byte) 0x8C;
How could I know if the first bit is an 1 or a 0 ?
Can anyone help me out ?
It depends what you mean by "first bit". If you mean "most significant bit" you can use:
// 0 or 1
int msb = (m & 0xff) >> 7;
Or if you don't mind the values being 0x80 or 0, just use:
// 0 or 0x80
int msb = m & 0x80;
Or in fact, as a boolean:
// Uses the fact that byte is signed using 2s complement
// True or false
boolean msb = m < 0;
If you mean the least significant bit, you can just use:
// 0 or 1
int lsb = m & 1;
If the first bit is the lowest bit (ie bit 0), then
if((m & 1) >0) ...
should do it.
In general,
if ((m & (1<<N)) > 0) ...
will give you whether or not bit N is set.
If, however, you meant the highest bit (bit 7), then use N=7.
Assuming you mean leftmost bit, bitwise and it with 0x80 and check if it is zero nor not:
public boolean isFirstBitSet(byte b) {
System.out.println((b & (byte)0x80));
return (b & (byte)0x80) < 0;
}
If you mean lowest order bit you will need to and with 0x01 and check a different condition:
public boolean isFirstBitSet(byte b) {
System.out.println((b & (byte)0x01));
return (b & (byte)0x80) > 0;
}
Use the bitwise and operator.
public class BitExample {
public static void main(String args[]) throws Exception {
byte m = (byte)0x8C;
System.out.println("The first bit is " + (m & (byte)0x01));
m = (byte)0xFF;
System.out.println("The first bit is " + (m & (byte)0x01));
}
}
// output is...
The first bit is 0
The first bit is 1
Its a bit of a hack but you can use
if(x >> -1 != 0) // top bit set.
This works for byte, short, int, long data types.
However for most types the simplest approach is to compare with 0
if (x < 0) // top bit set.
This works for byte, short, int, long, float, or double
(Ignoring negative zero and negative NaN, most people do ;)
For char type you need to know the number of bits. ;)
if (ch >>> 15 != 0) // top bit set.
This code gives you msb(most significant bit)/biggest number which is a
power of 2 and less than any given number.
class msb{
void main(){
int n=155;//let 110001010
int l=(Integer.toBinaryString(n)).length();//9
String w="0"+Integer.toBinaryString(i).substring(1);//010001010
i=Integer.parseInt(w,2);
System.out.println(n^i);//110001010^010001010=100000000
}
}

Java: Checking if a bit is 0 or 1 in a long

What method would you use to determine if the the bit that represents 2^x is a 1 or 0 ?
I'd use:
if ((value & (1L << x)) != 0)
{
// The bit was set
}
(You may be able to get away with fewer brackets, but I never remember the precedence of bitwise operations.)
Another alternative:
if (BigInteger.valueOf(value).testBit(x)) {
// ...
}
I wonder if:
if (((value >>> x) & 1) != 0) {
}
.. is better because it doesn't matter whether value is long or not, or if its worse because it's less obvious.
Tom Hawtin - tackline Jul 7 at 14:16
You can also use
bool isSet = ((value>>x) & 1) != 0;
EDIT: the difference between "(value>>x) & 1" and "value & (1<<x)" relies on the behavior when x is greater than the size of the type of "value" (32 in your case).
In that particular case, with "(value>>x) & 1" you will have the sign of value, whereas you get a 0 with "value & (1<<x)" (it is sometimes useful to get the bit sign if x is too large).
If you prefer to have a 0 in that case, you can use the ">>>" operator, instead if ">>"
So, "((value>>>x) & 1) != 0" and "(value & (1<<x)) != 0" are completely equivalent
For the nth LSB (least significant bit), the following should work:
boolean isSet = (value & (1 << n)) != 0;
You might want to check out BitSet: http://java.sun.com/javase/6/docs/api/java/util/BitSet.html
Bit shifting right by x and checking the lowest bit.
In Java the following works fine:
if (value << ~x < 0) {
// xth bit set
} else {
// xth bit not set
}
value and x can be int or long (and don't need to be the same).
Word of caution for non-Java programmers: the preceding expression works in Java because in that language the bit shift operators apply only to the 5 (or 6, in case of long) lowest bits of the right hand side operand. This implicitly translates the expression to value << (~x & 31) (or value << (~x & 63) if value is long).
Javascript: it also works in javascript (like java, only the lowest 5 bits of shift count are applied). In javascript any number is 32-bit.
Particularly in C, negative shift count invokes undefined behavior, so this test won't necessarily work (though it may, depending on your particular combination of compiler/processor).
How does it work?
The cleverness of this answer lies in that the sign bit of an integer is very easy to read: when that bit is set, then the value is negative; if not set, then the value is either zero or positive.
So the whole idea is to shift the xth bit exactly into the sign bit. That means a displacement of 31 - x to the left (or 63 - x, if value is 64 bits wide).
In java (and other languages as well), the ~ operator computes the bitwise NOT operation, which arithmetically equals to -x - 1 (no matter how wide x is).
Also the java << operator takes only the least significant 5 (or 6) bits of the right-hand side operand (whether 5 or 6 depends on how wide the left-hand side operand is: for int then 5; for long then 6). Arithmetically this is the same as the remainder of division by 32 (or 64).
And that is (-x - 1) % 32 = 31 - x (or (-x - 1) % 64 = 63 - x, for 64 bit wide value).
The value of the 2^x bit is "variable & (1 << x)"
My contribution - ignore previous one
public class TestBits {
public static void main(String[] args) {
byte bit1 = 0b00000001;
byte bit2 = 0b00000010;
byte bit3 = 0b00000100;
byte bit4 = 0b00001000;
byte bit5 = 0b00010000;
byte bit6 = 0b00100000;
byte bit7 = 0b01000000;
byte myValue = 9; // any value
if (((myValue >>> 3) & bit1 ) != 0) { // shift 3 to test bit4
System.out.println(" ON ");
}
}
}
If someone is not very comfortable with bitwise operators, then below code can be tried to programatically decide it. There are two ways.
1) Use java language functionality to get the binary format string and then check character at specific position
2) Keep dividing by 2 and decide the bit value at certain position.
public static void main(String[] args) {
Integer n =1000;
String binaryFormat = Integer.toString(n, 2);
int binaryFormatLength = binaryFormat.length();
System.out.println("binaryFormat="+binaryFormat);
for(int i = 1;i<10;i++){
System.out.println("isBitSet("+n+","+i+")"+isBitSet(n,i));
System.out.println((binaryFormatLength>=i && binaryFormat.charAt(binaryFormatLength-i)=='1'));
}
}
public static boolean isBitSet(int number, int position){
int currPos =1;
int temp = number;
while(number!=0 && currPos<= position){
if(temp%2 == 1 && currPos == position)
return true;
else{
temp = temp/2;
currPos ++;
}
}
return false;
}
Output
binaryFormat=1111101000
isBitSet(1000,1)false
false
isBitSet(1000,2)false
false
isBitSet(1000,3)false
false
isBitSet(1000,4)true
true
isBitSet(1000,5)false
false
isBitSet(1000,6)true
true
isBitSet(1000,7)true
true
isBitSet(1000,8)true
true
isBitSet(1000,9)true
true
declare a temp int and make it equal the original.
then shift temp >> x times, so that the bit you want to check is at the last position. then do temp & 0xf to drop the preceding bits. Now left with last bit. Finally do if (y & 1 == 0), if last bit is a 1, that should equal 0, else will equal 1. Its either that or if (y+0x1 == 0)... not too sure. fool around and see
I coded a little static class which is doing some of the bit operation stuff.
public final class Bitfield {
private Bitfield() {}
// ********************************************************************
// * TEST
// ********************************************************************
public static boolean testBit(final int pos, final int bitfield) {
return (bitfield & (1 << pos)) == (1 << pos);
}
public static boolean testNum(final int num, final int bitfield) {
return (bitfield & num) == num;
}
// ********************************************************************
// * SET
// ********************************************************************
public static int setBit(final int pos, final int bitfield) {
return bitfield | (1 << pos);
}
public static int addNum(final int number, final int bitfield) {
return bitfield | number;
}
// ********************************************************************
// * CLEAR
// ********************************************************************
public static int clearBit(final int pos, final int bitfield) {
return bitfield ^ (1 << pos);
}
public static int clearNum(final int num, final int bitfield) {
return bitfield ^ num;
}
}
If there are some questions flying around, just write me an email.
Good Programming!
Eliminate the bitshifting and its intricacies and use a LUT for the right and operand.

Categories

Resources