Please explain the logic behind Kernighan's bit counting algorithm - java

This question directly follows after reading through Bits counting algorithm (Brian Kernighan) in an integer time complexity . The Java code in question is
int count_set_bits(int n) {
int count = 0;
while(n != 0) {
n &= (n-1);
count++;
}
}
I want to understand what n &= (n-1) is achieving here ? I have seen a similar kind of construct in another nifty algorithm for detecting whether a number is a power of 2 like:
if(n & (n-1) == 0) {
System.out.println("The number is a power of 2");
}

Stepping through the code in a debugger helped me.
If you start with
n = 1010101 & n-1=1010100 => 1010100
n = 1010100 & n-1=1010011 => 1010000
n = 1010000 & n-1=1001111 => 1000000
n = 1000000 & n-1=0111111 => 0000000
So this iterates 4 times. Each iteration decrements the value in such a way that the least significant bit that is set to 1 disappears.
Decrementing by one flips the lowest bit and every bit up to the first one. e.g. if you have 1000....0000 -1 = 0111....1111 not matter how many bits it has to flip and it stops there leaving any other bits set untouched. When you and this with n the lowest bit set and only the lowest bit becomes 0

Subtraction of 1 from a number toggles all the bits (from right to left) till the rightmost set bit(including the righmost set bit).
So if we subtract a number by 1 and do bitwise & with itself (n & (n-1)), we unset the righmost set bit. In this way we can unset 1s one by one from right to left in loop.
The number of times the loop iterates is equal to the number of set
bits.
Source : Brian Kernighan's Algorithm

Related

Sum vs XOR menas x+a=x^a ,

Given an integer, 0<= x <=a , find each such that:
x+a=x^a ,
where denotes the bit wise XOR operator. Then print an integer denoting the total number of x's satisfying the criteria above.
for example a=5 then x=0,2
a+x=a^x;
I tried to solve this way. Is there any other way to reduce time complexity.
`public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long n = in.nextLong();
int cnt=0;
for(long i=0;i<=n;i++)
{
long m=i^n;
if(n+i==m)
cnt++;
}
System.out.println(cnt);
}`
n can have any bit not set in a and this formula will hold.
This means the number of bits to permutate will be 32 minus the number of bits set in a i.e. Integer.bitCount
long cnt = 1L << (32 - Integer.bitCount(a));
Note if a has 0 or 1 bit set, the number of solutions is greater than Integer.MAX_VALUE.
This solution could help you.
numberOfLeadingZeros give how many zeros before last set bit from left,
and bitCount give how many bits set for value a.
long count = 1L<<(64-Long.numberOfLeadingZeros(a) - Long.bitCount(a));
x+a=x^a
if x=5 and (a=0 or a=2) only two value satisfy this condition x+a=x^a
Logic:- **To check number of zero bit**.
for example x=10, in binary representation of x=1010.
Algorithm:
1010 & 1== 0000 so count=1 and 1010 >>1=101
101 & 1 !=0 so count will remain same 101>>1=10
10 & 1==00 so count = 2 and 10>>1=1
1 & 1 !=0 so again count remain same and 1>>1=0 (exit).
answer will 2 to power count means 4.
int xor(int x)
{
int count=0;
while((x!=0)
{
if((x&1)==0)
count++;
x=x>>1;
}
return 1<<count;
}
this loop will execute only number of bits available. and it will reduce time complexity

reverse bits in Java - O(n)

I'm trying to understand this code which reverses bits in O(n) time. I understand the time complexity, but I'm not able to understand the logic behind this code.
public static long reverse(long a) {
long result = 0;
int i = 31;
while(a > 0){
result += (a % 2) * Math.pow(2, i);
i--;
a = a/2;
}
return result;
}
To keep it simple, for example, if I take 12 (1100) and only 4 bits (set i = 3), my output will be 3 (0011). I get that and I'm able to derive the answer as well.
But can someone explain the logic behind this code? Thanks!
That code is
broken for half the possible bit patterns (all the negative numbers), and
O(n), not O(log n), where n is the number of bits in a
Very inefficient
Confusingly written
The algorithm works only for positive numbers and does:
extract the rightmost bit from a
set the corresponding bit from the left end
shift a one position to the right
It repeats as long as a > 0. If the value of a has some leading zero bits then this algorithm will be a little better than O(n).
Inefficiency results from remainder and division for bit extraction when masking and shifting would be much faster, although a modern compiler should be able to convert a/2 to a >> 1 and a%2 to a & 0x00000001. However I don't know if it would recognize Math.pow(2, i) as 0x00000001 << i;
Here's the explanation
i = 31 //number of bits in integer
Following has two parts
result += (a % 2) * Math.pow(2, i);
(a % 2) calculates last bit.
Multiplying anything with a positive power of 2 has the effect of left shifting the bits. (Math.pow(2, i) shifts to left i times.
so we are calculating unit place bit and placing it at ith position from the unit place, which is (31 - i) from the right, which effectively reverses the bit's position from left to right.
and finally
i--; //move to next bit
a = a/2; //chop the unit place bit to proceed to next.
That's it.

What is my code for inverting all the bits in a 32 bit integer producing the incorrect output?

This is from a hacker rank practice problem(not a competition) https://www.hackerrank.com/challenges/flipping-bits. Just doing this for practice.
The problem just asks you to take a set number for 32 bit integers and for each one, invert all the bits inside that integer and print out the result
Here's my code so far
static long getComplement(long c) {
long complement = 0;
for(int k = 31; k >= 0 ; k --) {
long evaluateBit = c >> k;
if(evaluateBit == 1) {
evaluateBit = 0;
} else {
evaluateBit = 1;
}
complement += evaluateBit << k;
}
return complement;
}
Here is my high level pseudo code thinking. I will evaluate every bit in the integer. To do this, I have to right shift the bit by its position(something that was at position 31 would have to be right shifted by 31 to get to position 0 so I can evaluate it). That's why my loop started at 31 and ends at 0. And then once i get the bit at that position, I will invert it with a conditional statement and then left shift the result by the same result. I will finally add it to the sum I am keeping (what was 0 * 2 ^ 31 will consist of 1 * 2 ^ 31)
Does anyone see any problems with my pseudo code?
There has to be a problem because when I tried running the code in my IDE, here is what I got when I debugged the code
I tried doing a test run with a input of 0.
After my first run(k=31), I somehow get a negative number. Does anyone know what the problem is or how I can fix this?
I made sure that I used the right shift operators as well, from How do shift operators work in Java?
Your first iteration changes the left most bit from 0 to 1. This is the sign bit, so of course you got a negative number.
EDIT :
change
evaluateBit = (c >> k);
to
evaluateBit = (c >> k) & 1;
In order for evaluateBit to really contain the value of a single bit.

How to find if two numbers are consecutive numbers in gray code sequence

I am trying to come up with a solution to the problem that given two numbers, find if they are the consecutive numbers in the gray code sequence i.e., if they are gray code neighbors assuming that the gray code sequence is not mentioned.
I searched on various forums but couldn't get the right answer. It would be great if you can provide a solution for this.
My attempt to the problem - Convert two integers to binary and add the digits in both the numbers separately and find the difference between the sum of the digits in two numbers. If the difference is one then they are gray code neighbors.
But I feel this wont work for all cases. Any help is highly appreciated. Thanks a lot in advance!!!
Actually, several of the other answers seem wrong: it's true that two binary reflected Gray code neighbours differ by only one bit (I assume that by « the » Gray code sequence, you mean the original binary reflected Gray code sequence as described by Frank Gray). However, that does not mean that two Gray codes differing by one bit are neighbours (a => b does not mean that b => a). For example, the Gray codes 1000 and 1010 differ by only one bit but are not neighbours (1000 and 1010 are respectively 15 and 12 in decimal).
If you want to know whether two Gray codes a and b are neighbours, you have to check whether previous(a) = b OR next(a) = b. For a given Gray code, you get one neighbour by flipping the rightmost bit and the other neighbour bit by flipping the bit at the left of the rightmost set bit. For the Gray code 1010, the neighbours are 1011 and 1110 (1000 is not one of them).
Whether you get the previous or the next neighbour by flipping one of these bits actually depends on the parity of the Gray code. However, since we want both neighbours, we don't have to check for parity. The following pseudo-code should tell you whether two Gray codes are neighbours (using C-like bitwise operations):
function are_gray_neighbours(a: gray, b: gray) -> boolean
return b = a ^ 1 OR
b = a ^ ((a & -a) << 1)
end
Bit trick above: a & -a isolates the rigthmost set bit in a number. We shift that bit by one position to the left to get the bit we need to flip.
Assumptions:
Inputs a and b are grey code sequences in binary reflected gray code.
i.e a's and b's bit encoding is binary gray code representations.
#convert from greycode bits into regular binary bits
def gTob(num): #num is binary graycode
mask = num >> 1
while mask!=0:
num = num^mask
mask >>= 1
return num; #num is converted
#check if a and b are consecutive gray code encodings
def areGrayNeighbors(a,b):
return abs(gTob(a) - gTob(b)) == 1
Few Test cases:
areGrayNeighbors(9,11) --> True (since (1001, 1011) differ in only one
bit and are consecutive numbers in decimal representation)
areGrayNeighbors(9,10) --> False
areGrayNeighbors(14,10) --> True
References:
method gTob() used above is from rodrigo in this post The neighbors in Gray code
public int checkConsecutive2(int b1, int b2){
int x = (b1 ^ b2);
if((x & (x - 1)) !=0){
return 0;
}else{
return 1;
}
}
If two numbers are in gray code sequence, they differ by one binary digit. i.e the exclusive OR on the two numbers returns a power of 2. So, find XOR and check if the result is a power of two.
This solution works well for the all the test cases written by CodeKaichu above. I would love to know if it fails in any cases.
public boolean grayCheck(int x, int y) {
int z = x^y;
return (z&z-1)==0;
}
An obvious answer, but it works.
Convert each gray code into its respective Binary form, subtract the two. If you answer is a binary equivalent of +1 or -1 then the two gray codes are adjacent.
This seems like an over kill, but when you're siting in an interview and don't know the correct method, this works. Also to optimize, one can check the single bit difference filter, so we don't waste time converting and subtracting numbers that we know for sure aren't adjacent.
If you just want to check if the input numbers differ by just one bit:
public boolean checkIfDifferByOneBit(int a, int b){
int diff = 0;
while(a > 0 && b > 0){
if(a & 1 != b & 1)
diff++;
a = a >> 1;
b = b >> 1;
}
if (a > 0 || b > 0) // a correction in the solution provided by David Jones
return diff == 0 // In the case when a or b become zero before the other
return diff == 1;
}
You can check if two numbers differ by one bit or not as follows. In this method, difference in the length of binary numbers are taken care of. Eg, the output for 11 (1011) and 3 (11) will be returned as true.
Also, this does not solve the second criteria for Gray code adjacency. But if you only want to check if the numbers differ by one bit, the code below will help.
class Graycode{
public static boolean graycheck(int one, int two){
int differences = 0;
while (one > 0 || two > 0){
// Checking if the rightmost bit is same
if ((one & 1) != (two & 1)){
differences++;
}
one >>= 1;
two >>= 1;
}
return differences == 1;
}
public static void main(String[] args){
int one = Integer.parseInt(args[0]);
int two = Integer.parseInt(args[1]);
System.out.println(graycheck(one,two));
}
}
If two numbers are in gray code sequence, they differ by one binary digit. i.e the exclusive OR on the two numbers returns a power of 2. So, find XOR and check if the result is a power of two.
python 3.8
a=int(input())
b=int(input())
x=a^b
if((x and (not(x & (x - 1))) )):
print("True")
else:
print("False")
I've had to solve this question in an interview as well. One of the conditions for the two values to be a gray code sequence is that their values only differ by 1 bit. Here is a solution to this problem:
def isGrayCode(num1, num2):
differences = 0
while (num1 > 0 or num2 > 0):
if ((num1 & 1) != (num2 & 1)):
differences++
num1 >>= 1
num2 >>= 1
return differences == 1

truncated binary logarithm

I have a question about this problem, and any help would be great!
Write a program that takes one integer N as an
argument and prints out its truncated binary logarithm [log2 N]. Hint: [log2 N] = l is the largest integer ` such that
2^l <= N.
I got this much down:
int N = Integer.parseInt(args[0]);
double l = Math.log(N) / Math.log(2);
double a = Math.pow(2, l);
But I can't figure out how to truncate l while keeping 2^l <= N
Thanks
This is what i have now:
int N = Integer.parseInt(args[0]);
int i = 0; // loop control counter
int v = 1; // current power of two
while (Math.pow(2 , i) <= N) {
i = i + 1;
v = 2 * v;
}
System.out.println(Integer.highestOneBit(N));
This prints out the integer that is equal to 2^i which would be less than N. My test still comes out false and i think that is because the question is asking to print the i that is the largest rather than the N. So when i do
Integer.highestOneBit(i)
the correct i does not print out. For example if i do: N = 38 then the highest i should be 5, but instead it prints out 4.
Then i tried this:
int N = Integer.parseInt(args[0]);
int i; // loop control counter
for (i= 0; Math.pow(2 , i) == N; i++) {
}
System.out.println(Integer.highestOneBit(i));
Where if i make N = 2 i should print out to be 1, but instead it is printing out 0.
I've tried a bunch of things on top of that, but cant get what i am doing wrong. Help would be greatly appreciated. Thanks
I believe the answer you're looking for here is based on the underlying notion of how a number is actually stored in a computer, and how that can be used to your advantage in a problem such as this.
Numbers in a computer are stored in binary - a series of ones and zeros where each column represents a power of 2:
(Above image from http://www.mathincomputers.com/binary.html - see for more info on binary)
The zeroth power of 2 is over on the right. So, 01001, for example, represents the decimal value 2^0 + 2^3; 9.
This storage format, interestingly, gives us some additional information about the number. We can see that 2^3 is the highest power of 2 that 9 is made up of. Let's imagine it's the only power of two it contains, by chopping off all the other 1's except the highest. This is a truncation, and results in this:
01000
You'll now notice this value represents 8, or 2^3. Taking it down to basics, lets now look at what log base 2 really represents. It's the number that you raise 2 to the power of to get the thing your finding the log of. log2(8) is 3. Can you see the pattern emerging here?
The position of the highest bit can be used as an approximation to it's log base 2 value.
2^3 is the 3rd bit over in our example, so a truncated approximation to log base 2(9) is 3.
So the truncated binary logarithm of 9 is 3. 2^3 is less than 9; This is where the less than comes from, and the algorithm to find it's value simply involves finding the position of the highest bit that makes up the number.
Some more examples:
12 = 1100. Position of the highest bit = 3 (starting from zero on the right). Therefore the truncated binary logarithm of 12 = 3. 2^3 is <= 12.
38 = 100110. Position of the highest bit = 5. Therefore the truncated binary logarithm of 38 = 5. 2^5 is <= 38.
This level of pushing bits around is known as bitwise operations in Java.
Integer.highestOneBit(n) returns essentially the truncated value. So if n was 9 (1001), highestOneBit(9) returns 8 (1000), which may be of use.
A simple way of finding the position of that highest bit of a number involves doing a bitshift until the value is zero. Something a little like this:
// Input number - 1001:
int n=9;
int position=0;
// Cache the input number - the loop destroys it.
int originalN=n;
while( n!=0 ){
position++; // Also position = position + 1;
n = n>>1; // Shift the bits over one spot (Overwriting n).
// 1001 becomes 0100, then 0010, then 0001, then 0000 on each iteration.
// Hopefully you can then see that n is zero when we've
// pushed all the bits off.
}
// Position is now the point at which n became zero.
// In your case, this is also the value of your truncated binary log.
System.out.println("Binary log of "+originalN+" is "+position);

Categories

Resources