Java Signed Right Shift - java

I have seen this in a java code.
int n = 300 //passed through a function
size = (n + 31) >> 5 //size = 10
what could be the significance of 5?
What is the significance of 31 //should something to do with int size (31 bit + 1 sign)
Thanks

The significance of 5 is that 32 = 2^5.
size = (n + 31) >> 5
sets size to ceiling(n/32), which is the number of 32-bit integers needed to store n bit flags.
The addition of 31 to n is to make sure that the dividend is at least as large as the smallest multiple of 32 greater than or equal to n.

Related

Binary arithmetic: why hash%n is equivalent to hash&(n-1)?

I have been studying Java HashMap source code, the part of it which decides in what bucket to put an object and saw this change in Java 7 (8) as compared to Java 6.
Additionally I conducted numerous experiments and both expressions yeild the same result:
hash % n
and
hash & (n - 1)
where n - the array length that must be power of 2.
I just cannot figure out why is it true? Is there any theorem or some math laws that prove these statement are equal? Basically I want to understand the inference and prove the equivalence of those two statements.
PS. If n is not a power of 2 number, the equivalence breaks immedeately.
If n is a power of two that mean its binary representation is 10000....,
n-1 for that matter is 1111111... with one less digit.
That means that binary &-ing with (n-1) preserves just exactly the number of bits in k that n-1 has set.
Example n = 8: 1000, n-1 = 7: 111
&-ing for example k = 201: 11001001
k % n = k & (n-1) = 11001001 & 111 = 001 = 1.
%-ing with a power of 2 means that in binary you just strip everything away that is above (including) the only set bit: for n = 8 that means stripping everything over (including) the 4th bit. And that is exactly what the &-ing does at well.
A side effect is that using & is commutative: hash & (n - 1) is equivalent to (n - 1) & hash which is not true for %, the jdk source code in many places uses the later, e.g. in getNode
Think about the bits in (n - 1) if n is a power of 2 (or ((1 << i) - 1), if you want to simplify the constraint on n):
If n is, say, 16 (= 1 << 4), then n - 1 is 15, and the bit representation of 15 and 16 (as 32-bit ints) are:
1 = 00000000000000000000000000000001 // Shift by 4 to get...
16 = 00000000000000000000000000010000 // Subtract 1 to get...
15 = 00000000000000000000000000001111
So just the lowest 4 bits are set in 15. If you & this with another int, it will only allow bits in the last 4 bits of that number to be set in the result, so the value will only be in the range 0-15, so it's like doing % 16.
However, note that this equivalence doesn't hold for a negative first operand:
System.out.println(-1 % 2); // -1
System.out.println(-1 & (2-1)); // 1
Ideone demo
The arithmetic rule for integer / and % is:
x*(y/x) + (y%x) = y
What about a negative hash -4 and a positive n 8?
8*0 + (-4%8) = -4
Hence modulo maintains the sign.
-4 % 8 = -4
-4 & 7 = 4
Or:
int t = hash%n;
if (t < 0) {
t += n;
}
assert t == (hash & (n-1));
So in the earlier java with %n hash had to be positive to begin with.
Now hash may be negative, more solid and better hashing.
So that was a sound reason for this subtle change in java source code.
Background:
2n is a 1 followed by n-1 0s (in binary).
2n - 1 is n-1 1s.
Hence for n being a positive power of 2, and some positive number h:
h % n == h & (n-1)
Another usage is to count bits in an int. The class Integer has just such a function.
int bits = 0;
while (x != 0) {
x &= x - 1;
++bits;
}

Trying to find the number of x's that satisfies n + x = n ^ x fails with timeout

I'm trying to solve the following problem from the section Bit Manipulation at the Hacker Rank site using new features of Java 8 such as Streams.
The problem description:
Given an integer, n, find each x such that:
0 <= x <= n
n + x = n ^ x
where ^ denotes the bitwise XOR operator. Then print an integer denoting the total number of x's satisfying the criteria above.
Constraints
0 <= n <= 1015
Sample Input: 5
Sample Output: 2
Explanation:
For n = 5, the x values 0 and 2 satisfy the conditions:
5 + 0 = 5 ^ 0 = 5
5 + 2 = 5 ^ 2 = 7
Thus, we print 2 as our answer.
Sample Input: 10
Sample Output: 4
Explanation:
For n = 10, the x values 0, 1, 4, and 5 satisfy the conditions:
10 + 0 = 10 ^ 0 = 10
10 + 1 = 10 ^ 1 = 11
10 + 4 = 10 ^ 4 = 14
10 + 5 = 10 ^ 5 = 15
Thus, we print 4 as our answer.
My code is as follows:
public class SumVsXor
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long count = LongStream.rangeClosed(0, n)
.filter(k -> k + n == (k ^ n))
.count();
System.out.println(count);
}
}
The problem is this code doesn't pass all the test cases.
It works for small values of n, but for large values such as 1000000000000000 it fails due to timeout.
I wonder whether LongStream can't handle Streams with that many elements.
The problem with your code is that it is very inefficient. For the case of n==1000000000000000, your Stream pipeline is performing 1,000,000,000,000,000 addition and XOR operations, which takes a long time. Testing for each number between 0 and n whether n + x == n ^ x would take a long time even if you use a for loop instead of Streams.
Instead of checking all the numbers between 0 and n, you should try to figure out a better way to calculate the required total number of x's. That fact that this problem appears under a "Bit Manipulation" section should give you a hint
to look into the bits of numbers that satisfy n + x == n ^ x.
Let's consider the case of n==1000000000000000. The binary representation of that large number is
0000000000000011100011010111111010100100110001101000000000000000
=== == = ====== = = = == == =
--- - - - - -- -- --- - ---------------
~~~~~~~~~~~~~~
In order for n + x to be equal to n ^ x, x must have a 0 value in all the bits corresponding with the 1 bits of n (marked with = above), and either 0 or 1 value in the bits corresponding with the 0 bits of n (marked with - above). This doesn't include the leading 0s (marked with ~ above), since x must be <= n, so any leading 0s in n must also have a 0 value in x.
This means that the total number of x's for which n + x == n ^ x is 2the number of 0s in n, not including leading 0s.
In the case of n = 1000000000000000, there are 30 such 0 bits, so the total number of x's that satisfy the requirement is 230.
Here's one way to compute the total number of x's :
long n = 1000000000000000L;
int zeroBitsCount = 0;
while (n > 0) {
if (n % 2 == 0) {
zeroBitsCount++; // counts the number of non-leading 0 bits
}
n = n >> 1; // divide n by 2 in order to examine the next bit in the next iteration
}
long total = 1L << zeroBitsCount; // the total is 2^(the 0 bits count)
I came to the same result, but via a different explanation, so thought I might post it here.
Eran's answer got to the same conclusion that I did : to modify the zeroes in the binary representation of the initial number - that is pretty straightforward.
Let's suppose our number is
101010100
so it has 5 zeroes.
you need all the possible combinations of:
a single zero
two zeroes
three zeroes
four zeroes
five zeroes
that is actually :
comb(1,5) + comb(2,5) + comb(3,5) + comb(4,5) + comb (5,5)
that is a well known formula being equal to:
pow(2,n) // where n is five in our case
from there the solution is obvious...
This is a simple question if you know little bit about XOR. I don't know much about java. But I can explain in python.
1.First convert the number to binary.
2.Count the number of zeros in that binary number.
3.print 2 ^ (number of zeros) and that's it.
Here is my python code.
n = int(input())
sum = 0
if n!=0:
n=str(bin(n))
for i in range(len(n)):
if n[i]=='0':
sum = sum + 1
print(2**(sum-1))
else: print(1)
The reason to decrement the sum by 1 is, in python it convert the number to the binary as this format. e.g: 0b'10101.
public static void main (String[] args) {
Scanner in = new Scanner (System.in);
long n = in.nextLong();
long count = 1L << (64-Long.bitCount(n)-Long.numberOfLeadingZeros(n));
System.out.println(count);
}

Adding all numbers from 1 to N which have number of set bits as 2

I have a question where I have to add numbers from 1 to N which have their set bits as 2. Like for N = 5 we should get value 8, as number 3 and 5 have 2 bits set to one. I am implementing the same in java. I am getting the o/p correct for int value but when it comes to the long values, either it's taking a lot of time or freezing, and when I submit the same on code judge sites, it's giving run time exceeded message. Please guide me how may I optimise my code to run it faster, thanks :)
public static void main(String[] args)
{
long n = 1000000L;
long sum = 0;
long start = System.currentTimeMillis();
for(long i = 1L ; i <= n ; i++)
{
if(Long.bitCount(i) == 2)
{
sum += i;
}
}
long end = System.currentTimeMillis();
System.out.println(sum);
System.out.println("time="+(end-start));
}
As #hbejgel notes, there is no point in looping over all numbers and checking their bit count. You can simply construct numbers with 2 bits and add them up.
You can construct a number with 2 bits by picking two different bit positions in the long, the "higher" bit and the "lower" bit":
long i = (1 << higher) + (1 << lower);
So, you can simply loop over all such numbers, until the value you have constructed exceeds your limit:
long sum = 0;
outer: for (int higher = 1; higher < 63; ++higher) {
for (int lower = 0; lower < higher; ++lower) {
long i = (1 << higher) + (1 << lower);
if (i <= n) {
sum += i;
}
if (i >= n) break outer;
}
}
Let's say we know the closest number, x, equal to or lower than N with 2 set bits, then we can use the formula for power series to quickly sum all positions of the two set bits, for example, if x = b11000, we sum
4*2^0 + S(4)
+ 3*2^1 + S(4) - S(1)
+ 2*2^2 + S(4) - S(2)
+ x
where S(n) = 2 * (1 - 2^n) / (1 - 2) 
= 2 + 2^2 + 2^3 ... + 2^n
With numbers encoded 2 out of 5, exactly two bits are set in every one-digit number. The sum is 45, with the exception of N×(N-1)/2 for 0≤N<9.
I think the question is supposed to discover the pattern.
Fast forward. Given a number N, you can tell the largest number
should count by bitmask from the first two bits are set. So you have
a smaller number M
Skip to next counted number Given any number with two bit set, next
largest number is the shift the second bit by one, until underflow.
Skip to next order When underflow happens on set two, shift the
highest bit by one and also the bit on it's right.
You don't really need a loop on N, but the bits it have.
Next question: can you answer a large number? which N >100,000,000
Next Next question: can you answer the same question for X bits when X>2

Strange Behavior when printing "all powers of 2 that fit in a long"

I'm attempting to print all powers of two from 2^0 onward that will fit into a long variable.
This is my code so far
long y = 0;
int iteration = 1;
for (y = 1; y < 9223372036854775807L; y *= 2) {
System.out.println("2 to the power of " + iteration + " is " +y);
iteration++;
This behaves as expected until 2^63 when the console prints
2 to the power of 62 is 4611686018427387904
2 to the power of 63 is -9223372036854775808
2 to the power of 64 is 0
Then the program continually returns
2 to the power of 64 is 0
2 to the power of 65 is 0
2 to the power of 66 is 0
And so on.
What is happening here?
When the final y *= 2 is performed y becomes a value larger than that which can be stored as a long. As longs are two's complement in java, where the most significant bit indicates if a number is positive or negative, when you make a long larger than its max value the most significant bit changes from a 0 to a 1, meaning the value of the long becomes negative so your loop will never terminate. There is a good video on two's complement on youtube for a better explanation.

Find the greatest odd number with a limited number of bits

I was trying to solve this question but the automated judge is returning "time limit exceeded" (TLE).
On the occasion of Valentine Day , Adam and Eve went on to take part in a competition.They cleared all rounds and got into the finals. In the final round, Adam is given a even number N and an integer K and he has to find the greatest odd number M less than N such that the sum of digits in binary representation of M is atmost K.
Input format:
For each test case you are given an even number N and an integer K
Output format:
For each test case, output the integer M if it exists, else print -1
Constraints:
1 &leq; T &leq; 104
2 &leq; N &leq; 109
0 &leq; K &leq; 30
Sample input:
2
10 2
6 1
Sample output:
9
1
This is what I have done so far.
static long play(long n, int k){
if(k==0) return -1;
if(k==1) return 1;
long m=n-1;
while(m>0){
long value=Long.bitCount(m); //built in function to count bits
if(value<=k ){
return m;
}
m=m-2;
}
return -1;
}
public void solve(InputReader in, OutputWriter out) {
long start=System.currentTimeMillis();
int t=in.readInt();
while(t-->0){
long n=in.readLong();
int k=in.readInt();
long result=play(n,k);
out.printLine(result);
}
long end=System.currentTimeMillis();
out.printLine((end-start)/1000d+"ms");
}
}
According to updated question N can be between 2 and 10^9. You're starting with N-1 and looping down by 2, so you get up to about 10^9 / 2 iterations of the loop. Not good.
Starting with M = N - 1 is good. And using bitCount(M) is good, to get started. If the initial bitcount is <= K you're done.
But if it's not, do not loop with step -2.
See the number in your mind as binary, e.g. 110101011. Bit count is 6. Let's say K is 4, that means you have to remove 2 bits. Right-most bit must stay on, and you want largest number, so clear the two second-last 1-bits. Result: 110100001.
Now, you figure out how to write that. And do it without converting to text.
Note: With N <= 10^9, it will fit in an int. No need for long.
You'll have to perform bitwise operations to compute the answer quickly. Let me give you a few hints.
The number 1 is the same in binary and decimal notation: 12 = 110
To make the number 102 = 210, shift 1 to the left by one position. In Java and many other languages, we can write this:
(1 << 1) == 2
To make the binary number 1002 = 410, shift 1 to the left by two positions:
(1 << 2) == 4
To make the binary number 10002 = 810 shift 1 to the left by three positions:
(1 << 3) == 8
You get the idea.
To see if a bit at a certain position is 1 or 0, use &, the bitwise AND operator. For example, we can determine that 510 = 1012 has a 1 at the third most significant bit, a 0 at the second most significant bit, and a 1 at the least significant bit:
5 & (1 << 2) != 0
5 & (1 << 1) == 0
5 & (1 << 0) != 0
To set a bit to 0, use ^, the bitwise XOR operator. For example, we can set the second most significant bit of 710 = 1112 to 0 and thus obtain 510 = 1012:
7 ^ (1 << 1) == 5
As the answer is odd,
let ans = 1, here we use 1 bit so k = k - 1;
Now binary representation of ans is
ans(binary) = 00000000000000000000000000000001
while(k > 0):
make 30th position set
ans(binary) = 01000000000000000000000000000001
if(ans(decimal) < N):
k -= 1
else:
reset 30th position
ans(binary) = 00000000000000000000000000000001
Do the same from 29th to 1st position

Categories

Resources