This question is related to but it is different in understanding how the code actually works. More precisely, I do not understand how numberOfTrailingZeros(int i) in java 8 here compute the final result. The code is as follows
public static int numberOfTrailingZeros(int i) {
// HD, Figure 5-14
int y;
if (i == 0) return 32;
int n = 31;
y = i <<16; if (y != 0) { n = n -16; i = y; }
y = i << 8; if (y != 0) { n = n - 8; i = y; }
y = i << 4; if (y != 0) { n = n - 4; i = y; }
y = i << 2; if (y != 0) { n = n - 2; i = y; }
return n - ((i << 1) >>> 31);
}
Now I understand the purpose of the shift operations from 16 to 2, but won't n have already the number of trailing zeros by the last shift operation:
y = i << 2; if (y != 0) { n = n - 2; i = y; }.
That is I do not understand the purpose of this particular line
n - ((i << 1) >>> 31);
why do we need that when n has already the right value?
Can anyone give a detailed example of what is going on?
Thanks!
I will try to explain the algorithm. It is a bit optimized, but I'll start with a (hopefully) more simplified approach.
It is used to determine the number of trailing zero bits of a 32 bit number, that is, how many zeros are on the right side (assuming most significant bit on left). The main idea is to divide the field in two half: if the right one is all zero we add the number of bits in the right half to the result and continue examining the left one (again dividing it); if the right one is not all zero, we can ignore the left one and continue examining the right one (adding nothing to the result).
Example: 0000 0000 0000 0010 0000 0000 0000 0000 (0x0002 0000)
first step (not java code, all numbers base 2, result is decimal):
i = 0000 0000 0000 0010 0000 0000 0000 0000
left = 0000 0000 0000 0010
right = 0000 0000 0000 0000
result = 0
since right is zero, we add 16 (actual number of bits in right part) to the result and continue examining the left part
second step:
i = 0000 0000 0000 0010 // left from previous
left = 0000 0000
right = 0000 0010
result = 16
now right is not zero, so we add nothing to result and continue with right part
third step:
i = 0000 0010 // right from previous
left = 0000
right = 0010
result = 16
right is not zero, nothing added to result, continue with right part
4th step:
i = 0010 // right from previous
left = 00
right = 10
result = 16
5th step:
i = 10 // right from previous
left = 1
right = 0
result = 16
now right is zero, so we add 1 (number of bits in right part) and there is nothing else to divide (that is the return line off original code)
result = 17
Optimizations: instead of having the left and the right part, the algorithm only examines the left left x-most bits of the number and just shift the right part into the left if the right one is not zero, example for first step:
y = i << 16; if (y != 0) { ... i = y;}
and, to avoid having an else part (I think), it starts the result with 31 (sum of all part lengths 1+2+4+8+16) and subtracts the bit count if the right side (after shifting the now left one) is not zero. Again for the first step:
y = i << 16; if (y != 0) { n = n - 16; ....}
Second optimization, last step, instead of
y = i << 1; if (y != 0) { n = n - 1; /* i = y not needed since we are done*/ }
return n;
it does just
return n - ((i << 1) >>> 31);
here ((i << 1) >>>31) is shifting the second bit (second leftmost, second highest bit) of i to leftmost position (eliminating the first bit) and then shifting it to rightmost position, that is, resulting in 0 if the second bit is zero, 1 otherwise. Which is then subtracted from the result (to undo the sum 31 from the beginning).
The first (leftmost) bit need not be directly examined. It only matters if all other bits are zero, that is, the number is 0, checked at the very beginning (if (i == 0) return 32;) or it is -1 in which case the initial value of result is returned: 31.
Related
I'm having trouble trying to reverse engineer this section of code; I need to be able to get x, y, z from l would anyone be able to point me in the right direction. Thanks
int l = ((X << 20) + (Y << 19) + Z);
The ranges are as follows
X = 0 - 4095
Y = 0 - 1
Z = 0 - 384,794
X being 0-4095 = 12 bits
Y being 0-1 = 1 bit
Z being 0-384794 = 19 bits
Java integers are 32 bit, so starting from 0:
int l = 0000 0000 0000 0000 0000 0000 0000 0000
+ X << 20 = the value of X, moved 20 places to the right. So:
int l = XXXX XXXX XXXX 0000 0000 0000 0000 0000
+ Y << 19 = the value of Y, moved 19 places to the right. So:
int l = XXXX XXXX XXXX Y000 0000 0000 0000 0000
+ Z = the value of Z, moved 0 places. So:
int l = XXXX XXXX XXXX YZZZ ZZZZ ZZZZ ZZZZ ZZZZ
Since no bits are ever overwritten, we can recover them:
int x = l >> 20 & 0xFFF; //reverse the shifting (by 20), then isolate the X bits (0xFFF = 12 bits set to 1, equal to 4095)
int y = l >> 19 & 0x1; //reverse the shifting (by 19), then isolate the Y bit (0x1 = 1 bit set to 1, equal to 1)
int z = l & 0x7FFFF; //no shifting to reverse, but we still isolate the Z bits (0x7FFFF = 19 bits set to 1, equal to 524287)
Recently I was given a codility problem which says the following code has a bug.
So, the code problem is that we have a 30-bit unsigned integer from N[29]... N[0] and performing the right cyclic shift (>>) should give us a number like N[0]N[29]... N[1].
Our goal is to find the number of right shifts which produce the maximum value achievable from a given number.
For Example:
for N = 9736 (00 0000 0000 0000 0010 0110 0000 1000)
9736 >> 1 = 4868 -> 00 0000 0000 0000 0001 0011 0000 0100
.
.
.
9736 >> 11 = 809500676 -> 11 0000 0100 0000 0000 0000 0000 0100
.
.
till 30 (as we have 30 bits integers)
from the example above on the 11th iteration, we receive the maximum number possible for 9736.
Hence the answer = 11
Given Code:
int shift(int N) {
int largest = 0;
int shift = 0;
int temp = N;
for (int i = 1; i < 30; ++i) {
int index = (temp & 1);
temp = ((temp >> 1) | (index << 29));
if (temp > largest) {
largest = temp;
shift = i;
}
}
return shift;
}
N is in range [0... 1,073,741,823]
I tried but couldn't find the bug here or the test case where this fails.
It fails for 0b10000...000 (0x20000000), Because the largest value is for shift==0
the simplest solution is to define largest as N instead of 0.
I need to switch the first half and the second half of a byte: Make 0011 0101 to 0101 0011 for example
I thought it might work this way:
For example, i have 1001 1100
i bitshift to the left 4 times and get 1111 1001(because if the first bit is a 1 the others become a one too)
i bitshift to the right 4 times and get 1100 0000(the second half of the byte gets filled with 0s)
i don't want 1111 1001 but 0000 1001 so i do 0x00001111 & 1111 1001 (which filters the frist 4 bits) to make 1111 1001 to 0000 1001
then i add everything up:
0000 1001 + 1100 0000 = 1100 1001
I got this:
bytes[i] = (byte) (( 0x00001111 & (bytes[i] >> 4)) + (bytes[i] << 4)
);
here is one output: 11111111 to 00000001
I do not really understand why this is happening, I know the binary System and I think I know how bitshifting works but I can't explain this one.
Sorry for bad english :)
Be careful with the >>> operation, which shifts the sign bits without sign extending so zero bits will fill in on the left. The problem is that it is an integer operation. The >> works the same way except it sign extends thru the int.
int i = -1;
i >>>= 30;
System.out.println(i); // prints 3 as expected.
byte b = -1;
b >>>= 6;
System.out.printnln(b); // prints -1 ???
The byte is still -1 because byte b = -1 was shifted as though it was an int then reassigned to a byte. So the byte remained negative. To get 3, you would need to do something that seems strange, like the following.
byte b = -1;
b >>>=30;
System.out.println(b); // prints 3
So to do your swap you need to do the following;
byte b = 0b10100110;
b = (byte)(((b>>>4)&0xF)|(b<<4));
The 0xF mask, masks off those lingering high order bits left over from the conversion from integer back to byte.
I'm not sure about the syntax for bit manipulation in Java, although here's how you can do it.
bitmask = 0x1111;
firstHalf = ((bytes[i] >> 4) & bitmask);
secondHalf = ((bytes[i] & bitmask) << 4)
result = firstHalf | secondHalf;
I don't want 1111 1001 but 0000 1001
If so, you need to use shift right zero fill operator(>>>) instead of preserving sign of the number.
I don't think the formula found works properly.
public byte reverseBitsByte(byte x) {
int intSize = 8;
byte y=0;
for(int position=intSize-1; position>0; position--){
y+=((x&1)<<position);
x >>= 1;
}
return y;
}
static int swapBits(int a) {
// Написать решение сюда ↓
int right = (a & 0b00001111);
right= (right<<4);
int left = (a & 0b11110000);
left = (left>>4);
return (right | left);
}
Could you please let me know is there any best way to find that in binary representation of this number set bits are followed by unset bits only like -
4 - 100
6 - 110
8 - 1000
12 - 1100
private static boolean setBitFollowedByUnsetBits(int num) {
String str = Integer.toBinaryString(num);
int len = str.length();
int countof1 = str.indexOf('0');
int lastIndOf0 = str.lastIndexOf('0');
int countof0 = lastIndOf0 -countof1;
int lastIndOf1 = str.lastIndexOf('1');
if((!(lastIndOf1 > countof1) && (lastIndOf1 < lastIndOf0))) {
return ((num >> countof0+1)==((2 << countof1-1)-1));
}
return false;
}
This is what the logic i have written but i am looking for better solution which is much efficient .
Elaborating on #Alberto's hint:
You are looking for a bit pattern like 0000 0000 0111 1111 1100 0000 0000 0000 (I assume 32-bit integers):
some leading zero-bits (none is also OK)
a block of one-bits (at least one)
a block of zero-bits (at least one)
Special cases can be all zero-bits (N==0), or a number ending with a one-bit (having no trailing zero-bits). Let's first look at the generic case:
Having a binary number like N=xxxx1000, then N-1 is xxxx0111, replacing all the trailing zero-bits by one-bits, the rightmost one-bit by a zero-bit, and leaving the higher bits unchanged.
ORing N with N-1 like int K = N | (N-1); replaces trailing zero-bits with one-bits:
N = xxxx1000
N-1 = xxxx0111
--------
K = xxxx1111
We want the xxxx part to be something like 0001. Now, let's invert K:
~K = yyyy0000
where yyyy is the bitwise inverse of xxxx, and should look like 1110. So, once again, we can check for the trailing zero-bits and set them with int L = (~K) | ((~K)-1);. The result sould now be all one-bits if there was only one block of one-bits in the original number.
Now the special cases:
If there was no one-bit at all in N, the result will also give all ones. As the one-bits block is missing, the result should be false, needing a special handling.
A number consisting of just one block of one-bits will also result in all ones. But as the trailing zero-bits are missing, it should return false, needing a special handling as well, which just has to look at the last bit being zero.
So the code code look like:
private static boolean setBitFollowedByUnsetBits(int num) {
if (num == 0) return false;
if ((num & 1) == 1) return false;
int invK = ~ (num | (num-1));
int indicator = invK | (invK-1);
return indicator == 0xffffffff;
}
You could adapt Brian Kernigan's Algorithm
https://www.geeksforgeeks.org/count-set-bits-in-an-integer/
a) Initialize count: = 0
b) If integer n is not zero
Do bitwise & with (n-1) and assign the value back to n
{ n: = n&(n-1) }
Increment count by 1
go to step b
c) Else return count
As explained in the link above Subtraction of 1 from a number toggles all the bits (from right to left) till the rightmost set bit(including the rightmost set bit). So if we subtract a number by 1 and do bit-wise & with itself (n & (n-1)), we unset the rightmost set bit. If we do n & (n-1) in a loop and count the no of times loop executes we get the set bit count.
I think that more efficient way is to do bitwise checking instead of string -> integer transformation and operating with strings.
private static boolean check(int value) {
int h = SIZE - numberOfLeadingZeros(value);
boolean one = false;
boolean zero = false;
for (int i = h - 1; i >= 0; i--) {
int mask = 1 << i;
if ((value & mask) == mask) {
if (!zero) {
one = true;
} else {
return false;
}
} else {
if (one) {
zero = true;
} else {
return false;
}
}
}
return one && zero;
}
This is how I would do it.
private static boolean setBitFollowedByUnsetBits(int num) {
int withoutTrailingZeros = num >>> Integer.numberOfTrailingZeros(num);
return num != 0 && (withoutTrailingZeros & withoutTrailingZeros + 1) == 0;
}
This works because your problem is really to shift out the trailing zeros, which Java has a fast built in function for, then to test if the remaining number has all bits set (up to the most significant bit). You can do this with a bitwise and, as for any number n, n & n + 1 is only 0 if n has all bits set (see below). I assume you don't want 0 to return true because it has no bits set, but you can remove the num != 0 && if this isn't the case.
111 // 7
& 1000 // 8
= 0000 // 0, so 7 has all bits set
101 // 5
& 110 // 6
= 100 // 4, so 5 does not have all bits set
Edit: if the number must have some trailing zeros, you can also check for withoutTrailingZeros != num to be true.
what does this piece of code mean ...Can anyone explain how does this work..
sum += (i & (1<<j)) != 0 ? n[j] : 0;
full code:
int max = (1 << N)-1;
//System.err.println(max);
String res = "No";
for (int i = 0; i <= max; i++)
{
long sum = 0;
for (int j = 0; j < N; j++)
{
sum += (i & (1<<j)) != 0 ? n[j] : 0;
}
//System.err.println(i + " " + sum);
if(sum == m){
res = "Yes";
break;
}
Let's say that a = 0011 1100
So with the Binary Left Shift Operator (<<). The left operands value is moved left by the number of bits specified by the right operand.
A << 2 will give 240 which is 1111 0000
So in your code you have a loop for i and a loop for j
And this line
sum += (i & (1<<j)) != 0 ? n[j] : 0;
So for your second iteration of i = 2 and first iteration of j = 1
First the left shift operator will shift left all bits one position, resulting in 0000 0001 << 1 = 0000 0010 (or 2)
then you have a binary and comparison which will be i (0000 0010 in binary) & (0000 0010) = 0000 0010 (or 2)
And this and result will be asked if it's distinct of zero. If this result it's true then sum will be increased by the number in the n[j] array position, else will not be increased.
Java has a shortened version of an if else command. The use of it is very easy, once you understand it.
It’s written:
x ? y : z;
Here the question mark and the colon will take the place of the commands if and else.
This means:
condition ? inCaseOfTrue : elseCase;
With this code i & (1 << j) you get jth bit of i in binary representation. And if it equals 1 then you add n[j] to sum.
The full code shows you calculate all possible sums with selecting some elememts of array n;