Java Non Arithmetical Adder [duplicate] - java

This question already has answers here:
Performing arithmetic operations in binary using only bitwise operators [duplicate]
(2 answers)
Closed 8 years ago.
I found some code to add two numbers using XOR and AND without using any arithmetical operators.
I understand that x^y equates to the sum and that x&y equates to the carry. However I don't understand why the carry must be left shifted? My knowledge of the left bitwise shift is that is the same as multiplying by two. Why is the carry being multiplied by two?
public static int add(int x, int y) {
// Iterate till there is no carry
while (y != 0)
{
// carry
int carry = x & y;
// Sum
x = x ^ y;
y = carry << 1;
}
return x;
}
Any guidance appreciated.

Lets try with two small integer x=5 which binary equivalent is 101 and y=1, which binary equivalent is 001.
Now, why I am talking about binary or more specifically, want to deal with bits? Because XOR is a bit wise operation.
So, if you run XOR operation between x and y, the result is following:
x = x^y = 101 ^ 001 = 100 (decimal :4)
See, just XOR operation between two numbers don't give us the sum. (sum of 5 and 1 should be 6, not 4) We use the carry, to get the exact sum. Actually, the algorithm is designed in a way, so that it gives us the correct answer.
Now, lets see, how using carry in this algorithm, gives us the correct answer.
Since,
carry = x & y = 101 & 001 = 1 (decimal 1)
According to your program, y = carry << 1;
So, y will now become = 001 << 1 = 010 (decimal :2)
The loop will keep running, until y becomes zero.
If you run the loop again (since y=2 and not zero)
x = x ^ y = 100 ^ 010 = 110 (decimal :6)
carry = x & y= 100 & 010 = 0 (decimal 0)
Now, the XOR between the new value of x and y is 6 which is exactly the sum of 5 and 1. Look at carry, its value is now 0.
Our y will also become 0 now, because right shifting 0 will also give us 0. Since y is now zero, the loop will not run anymore and we got our sum by returning x!

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);
}

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

Want to Convert decimal value in 2 raised to format and want to know its power of 2 in java

I have one decimal value like 65 and I want to divide this value in 2 raised to format.
For example, I have this type rule:
If I get 42 as a decimal number, I want to divide first 42 number in format of 2 raised to. Then, I want to output its power only, like:
OutPut : 1,3,5
For example, if I have 65 as a decimal number, then I want 6,0 as its output, because (2 raised to 6) + (2 raised to 0) = 65.
Thanks
Anybody can help me how I can achieve this thing in Java.
You can repeatedly compare the least significant bit, counting as you go, and right-shifting the number to look at each bit in turn:
int n = 65
int d = 0;
while (n > 0) {
if ((n & 1) == 1) { // check LSB
System.out.println(d);
}
n >>>= 1; // shift right
++d; // inc digit count
}
Integer.toString(65, 2);
Does the following output:
1000001
Then you work on the String.
This can be improved, but I think it'll do the job.
int n = 42;
String binary = Integer.toBinaryString(n);
for(int i = binary.length() - 1; i >= 0; i--){
if(binary.charAt(i) == '1')
System.out.print(i+1);
}
Here is the algorithm:
Find a log base 2 of given number x=log(2, input)
Find the floor and the ceiling of the result y = floor(x), z=ceiling(x)
Find 2^y, 2^z and choose the one closer to the input.
calculate the diff = (input - 2^(x or y)) and do the same for the diff recursively until dif=0.

I need some help with a Java recursion problems

This is my first problem:
gcd(x,y)
if (x < y)
gcd(y,x)
else
if (y = 0)
return x
else
return gcd(y, x mod y)
This is my second problem:
public static int Test2(int x, int y) {
if (x > y) {
return 10;
} else {
return Test2(x-5, y+5) + 5;
}
}
The question is: What is returned for gcd(84, 21)?
a. 84
b. 21
c. 3 (This is the correct answer)
d. 10
X equals 84 and y equals 21. So I run them through the Algorithm class. 84 is not less than 21 so I skip that if statement. 84 is not equal so I skip that statement. I go to return gcd(y, x mod y). I don’t understand what is mod and how do you figure out what it means?
Second problem!
Question: What is returned for Test2(18,5)?
A. 5
B. 10
I choose ten , because x is greater than y and when processed to the if statement. It returns a value of ten. The if statements does run anything but the return statement.
C. 15 The answer is 15.
D. 20
mod is the modulo function. It's the rest when when you divide two integers. For example,
1 mod 3 = 1
2 mod 3 = 2
3 mod 3 = 0
4 mod 3 = 1
10 mod 4 = 2
10 is the correct answer for the second question, your argument is correct.
The modulo operator returns the remainder of a divison operation. e.g. 3 mod 2 = 1 since 1 is the remainder. % is commonly used as the symbol for mod. In this example 84 mod 21 equals 0 since 21 divides evenly into 84 four times.
x mod y is not valid Java, x % y is and it means modulo; that what if left after an integer division of x by y.
Btw, what do you mean with this is the answer and the answer is 15? Better to think the problem through and explain your own answer.

Categories

Resources