I was asked this question on the interview. I didn't answer and actually I don't understand how it works.
int add(int x, int y)
{
while (y != 0)
{
int carry = x & y;
x = x ^ y;
y = carry << 1;
}
return x;
}
I'm not asking why does it produce a correct answer... First of all, why does the algorithm eventually stop? To me it's not that obvious.
In order for it to stop, carry has to become 0. Can't someone explain it in a nutshell?
line 1 : int carry = x & y;
line 2 : x = x ^ y;
line 3 : y = carry << 1;
if x = 1; y = 2;
Binary for each number:
0 = 00
1 = 01
2 = 10
3 = 11
for line 1 code,
& (bitwise AND)
Binary AND Operator copies a bit to the result if it exists in both operands
x is 1 => 01
y is 2 => 10
result carry is => 00 (0)
for line 2 code,
^ (bitwise XOR)
Binary XOR Operator copies the bit if it is set in one operand but not both.
x is 1 => 01
y is 2 => 10
result x is => 11 (3)
for line 3 code,
variable carry needs to shift left for 1 bit,
so now carry is 0 => 00 and shift 1 bit left means carry is now 0. The result y is (0). And while loop stop because y is 0 now.
The final result for x is 3.
Hope this will help you.
Let's take an example:
x=13(1101)
y=9(1001)
Loop 1:
-----------------
y!=0 -> carry=(1101)&(1001)=1001(9) [AND Op]
x=(1101)^(1001)=0100(4) [XOR Op]
y=carry<<1 -> y=(carry)x2=10010(18)
Loop 2:
-----------------
y!=0 -> carry=(0100)&(10010)=00000(0)
x=(0100)^(10010)=10110(22)
y=carry<<1 -> y=0
loop terminated.
therefore,x is 22.So,x^y store the sum part and x&y store the carry part,and then carry(x&y) is shifted to match the digit with x^y,and finnally XOR them and store into x.
x is the resultant.
In a nutshell its about using y (and the "carries/x&y" it becomes) to modify x until it becomes the sum of both ints. For example,
y=1 (....0001), x=anything (either .....0 or .....1)
if x ends with 0, x&y=0
//x^y = x becomes ....001 (thereby adding 1)
//since x&y=0 the loop stops
if x ends with 1, x&y=1
//x^y = x
//since y= x&y<<1, new y=(.....000010)
if x ends with 01, x&y=0
//x^y = x becomes ....010 (thereby adding 1)
//since x&y=0 the loop stops
if x ends with 11, x&y=1
//x^y = .....01
//since y= x&y<<1, new y=(......000100)
if x ends with 011
//stuff happens and x becomes ....100 (thereby adding 1)
//loop stops
if x ends with 111
//...
//if x ends with 111111, x becomes ....1000000 (thereby adding 1)
//if x ends with 1111111, x becomes ....10000000 (thereby adding 1)
//if x ends with 11111111, x becomes ....100000000 (thereby adding 1)
//well you get the idea
The same logic is applicable to all values of y, and is not that much different from normal addition only that there are now 2 possible digits (0 and 1) instead of the usual 10 (0 to 9).
Related
I have the following code:
public static void main(String[] args) {
int a = 3;
int b = 7;
int x = b; // x=b
int res = a; // res = a
int y = 1;
int invariant = 0;
System.out.println("a|b|x|y|res|invariant");
while (x > 0) {
if (x % 2 == 0) {
y = 2 * y;
x = x / 2;
} else {
res = res + y;
y = 2 * y;
x = (x - 1) / 2;
}
invariant = y + 2;
String output = String.format("%d|%d|%d|%d|%d|%d", a,b,x,y,res,invariant);
System.out.println(output);
}
// < res = a + b >
}
Which gives the following output:
a|b|x|y|res|invariant
3|7|3|2|4|4
3|7|1|4|6|6
3|7|0|8|10|10
However, if I change the numbers, the invariant isn't equal to the res anymore. Therefore my loop invariant for this problem is not correct.
I'm struggling really hard to find the correct loop invariant and would be glad if there's any hint that someone can give me.
My first impression after looking into the code and my results is that the loop invariant changes based on a and b. Let's say both a and b are odd numbers as they are in my example, then my Loop invariant is correct (at least it seems like it)
Is it correct to assume a loop variant like the following?
< res = y - 2 && a % 2 != 0 && b % 2 != 0 >
I did use different numbers and it seems like anytime I change them there's a different loop invariant and I struggle to find any pattern whatsoever.
I would really appreciate if someone can give me a hint or a general idea on how to solve this.
Thanks
This loop computes the sum a+b.
res is initialized to a.
Then, in each iteration of the loop, the next bit of the binary representation of b (starting with the least significant bit) is added to res, until the loop ends and res holds a+b.
How does it work:
x is initialized to b. In each iteration you eliminate the least significant bit. If that bit is 0, you simply divide x by 2. If it's 1, you subtract 1 and divide by 2 (actually it would be sufficient to divide by 2, since (x-1)/2==x/2 when x is an odd int). Only when you encounter a 1 bit, you have to add it (multiplied by the correct power of 2) to the result. y Holds the correct power of 2.
In your a=3, b=7 example, the binary representation of b is 111
In the first iteration, the value of res is a + 1 (binary) == a + 1 = 4
In the second iteration, the value of res is a + 11 (binary) == a + 3 = 6
In the last iteration, the value of res is a + 111 (binary) == a + 7 == 10
You could write the invariant as:
invariant = a + (b & (y - 1));
This takes advantage of the fact the at the end of the i'th iteration (i starting from 1), y holds 2^i, so y - 1 == 2^i - 1 is a number whose binary representation is i 1 bits (i.e. 11...11 with i bits). When you & this number with b, you get the i least significant bits of b.
I'm trying to swap two ints - x and y in the example, and do it in one line without a library function.
So I started with this:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
y ^= x;
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
The output was 4, 3, 7, 3, 7, 4, 3, 4 as expected. All good so far.
Next up was this:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
y ^= (x ^= y);
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
The output was 4, 3, 7, 4, 3, 4 as expected once again. Still good so far.
Then finally this:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
x ^= (y ^= (x ^= y));
System.out.println(x);
System.out.println(y);
At this stage the output became 4, 3, 0, 4. Now I know that the 0 is a result of 4 ^ 4 because the x assignment wasn't complete at that time - why is this happening? Why doesn't the x ^= y actually assign 7 to the x variable so that it becomes 7 ^ 4 for the last assignment?
Let's try to expand your last expression.
It evaluates to,
x = x^(y = y^ (x = x^y));
Note that expressions are evaluated from left to right,
it becomes,
x = 4 ^ (y = 3 ^ (x = 4 ^ 3));
Now, the problem has become obvious. Right?
Edit:
To clear come confusion, let me try to explain what I mean by evaluating from left to right.
int i = 1;
s = i + (i = 2) + i;
Now, the expression will evaluate to,
s = 1 + 2 + 2;
Notice that i on the left of assignment was 1, but on the right of assignment (and on the assigment) was evaluated to 2, because the evaluation is from left to right, when it came to the 2nd and 3rd part of the expression, is value was 2.
The order of evaluation is defined in chapter 15 of the JLS. Item 15.7.1 says:
If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.
To explain further, they have two examples of computations that involve assignments. Here the assignment is on the left hand of the operator:
int i = 2;
int j = (i=3) * i;
System.out.println(j);
And they specifically say that the result is 9 and is not allowed to be 6. That is, the (i=3) is both calculated as 3 and i is assigned 3 before being multiplied with itself.
But in the second example:
int a = 9;
a += (a = 3); // first example
System.out.println(a);
int b = 9;
b = b + (b = 3); // second example
System.out.println(b);
The JLS specifies that both prints should produce 12, and are not allowed to produce 6. That is, because the assignment to b is on the right side, the value of the left b (or the implicit left a in the += operation), the value before that assignment is fetched and saved first, and only then the operation inside the parentheses is performed.
Internally, expressions are broken down into JVM operations that push and pop values onto an "operand stack". If you think about it like that - that in b = b + (b=3) The value of b is first pushed onto the operand stack, then the (b=3) is performed and its value is then added to the value popped from the stack (old value of b), it will make sense. At this point, the left hand b just stands for "What the value of b was when it was pushed on the stack" and not for the "current value of b".
Lets divide and compute.
The innermost parenthesis executes first and after all the parenthesis resolved, then the expression executes from left to right.
x ^= (y ^= (x ^= y)); // initial statement
x = x^(y = y^ (x = x^y)); //equals to
() have the highest precedence
x = x^(y = y^ (x = 3^4)); // first highest precedence ()
x = x^(y = y ^ (x = 7)); // still the first x is 3
x = 4 ^(y = 3 ^ (x = 7)); // now 3 ^ 7 =4
x = 4 ^ 4; // now 3 ^ 7 =4
x= 0;
I have two integers x and y.
Rule:
If x > y : x = x - y and y = 2 * y;
If y > x : y = y - x and x = 2 * x;
If y == x : not infinite loop
The question is, will the two integers be an infinite loop or not?
Here is my code:
private static boolean IsPairLoop(int first, int second)
{
boolean loop = false;
HashMap<Integer, Integer> round_record = new HashMap<>();
int[] first_round = new int[]{first, second};
while ((first_round[0] != -1 && first_round[1] != -1))
{
if (round_record.containsKey(first_round[0]))
{
loop = true;
break;
}
round_record.put(first_round[0], first_round[1]);
PlayRound(first_round);
}
return loop;
}
private static void PlayRound(int[] round)
{
if (round[0] > round[1])
{
round[0] -= round[1];
round[1] += round[1];
}
else if (round[0] < round[1])
{
round[1] -= round[0];
round[0] += round[0];
}
else
{
round[0] = -1;
round[1] = -1;
}
}
This works fine for small integers. However, this is painfully slow when the integer difference is really large. Integer range is 1 to 2^30 for both x and y. What can I do to make this fast even when the integers difference is large?
In this problem, the sum x + y is invariant, and if it is odd, x == y is impossible.
Then if x and y have the same parity, after one iteration they become both even and remain so, and the problem is unchanged if you divide both by 2.
Hence the "instantaneous" solution:
while (x + y) & 1 == 0:
if x == y:
print "Not infinite"
break
if x > y:
x= (x - y) / 2
else:
y= (y - x) / 2
else:
print "Infinite"
As one of the arguments loses at least one bit on every iteration, there are never more than 64 iterations for 32 bits integers (and in practice much less, most of the time 0 !).
A variant is possible and can make sense for bignumbers:
if x == y, conclude finite.
if x and y have a different number of trailing zeroes, conclude infinite.
otherwise, discard the trailing zeroes and perform the reduction according to x > y or y > x and loop.
Instead of using a hashmap, use Floyd's cycle detection algorithm. Not only will this avoid large memory use, it will also avoid costly boxing and unboxing between int and Integer.
A second optimisation is to re-write the recurrence relations via a change of variables:
s = x+y
t = x-y
Then the recurrence relations become:
if t=0, stop
if t>0, s'=s, t'=2t-s
if t<0, s'=s, t'=2t+s
Note in this formulation, only the t variable changes.
The code (untested) will look something like this:
private static int step(int s, int t) {
if (t>0) return 2*t - s;
if (t<0) return 2*t + s;
return 0;
}
private static boolean IsPairLoop(int first, int second) {
int s = first+second;
int t_slow = first-second;
int t_fast = t_slow;
while(t_slow != t_fast) {
t_slow = step(s, t_slow);
t_fast = step(s, step(s, s_fast));
}
return t_slow != 0;
}
You may need to replace int with long if first+second can overflow.
I think, given the preconditions, you never get a t that goes off to infinity (since it's always true that |t| < s). But you may wish to double-check, perhaps adding some sort of assertion into your code.
Let’s work backwards a bit. What can produce x == y? The difference between the previous x and y has to be equal to twice the smaller of the two, i.e. the larger has to be three times the smaller. Things that don’t loop infinitely so far:
{n, n}
{n, 3n}
Where can {n, 3n} come from? Either
n is a difference a − b for some a > b, and 3n = 2b
3(a − b) = 2b
3a − 3b = 2b
3a = 5b
a = 5/3 b
A pair {m, 5/3 m} is something that produces {n, 3n} on the next step. (m has to be divisible by 3, but that’s okay.)
3n is a difference a − b for some a > b, and n = 2b
(a − b)/3 = 2b
a − b = 6b
a = 7b
A pair {m, 7m} is the only other thing that can produce {n, 3n} on the next step.
An updated list:
{n, n}
{n, 3n}
{n, 7n}
{n, 5/3 n}
Seems like a good time to generalize those last steps.
{n, qn} happens when:
n is a difference a − b for some a > b, and qn = 2b
q(a − b) = 2b
qa − qb = 2b
qa = (2 + q)b
a = (2 + q)/q b
or qn is a difference a − b for some a > b, and n = 2b
(a − b)/q = 2b
a − b = 2qb
a = (2q + 1)b
So if q = m/n is in the list, these are also in the list:
(2n + m)/m
(2m + n)/n
q = 1 generates:
(2 + 1)/1 = 3
2×1 + 1 = 3
q = 3 generates:
3
(2 + 3)/3 = 5/3
2×3 + 1 = 7
q = 5/3 generates:
3
5/3
7
(2 + 5/3)/(5/3) = (6 + 5)/5 = 11/5
(2×5/3) + 1 = 10/3 + 1 = 13/3
q = 7 generates:
3
5/3
7
11/5
13/3
(2 + 7)/7 = 9/7
2×7 + 1 = 15
Hmm… that’s pretty interesting. Let’s sort the list by the numerator:
3/1
5/3
7/1
9/7
11/5
13/3
15/1
Based on that pattern, I’d expect 17/15 to come next. Generating a list sorted by denominator with a computer:
3/1
7/1
15/1
31/1
63/1
5/3
13/3
29/3
61/3
11/5
27/5
59/5
9/7
25/7
57/7
23/9
55/9
21/11
53/11
19/13
51/13
17/15
49/15
47/17
45/19
43/21
41/23
39/25
37/27
35/29
33/31
Looks an awful lot like m/n where n is odd, m > n, and m + n is a power of two. So one way to optimize your algorithm would be:
private static boolean isPairLoop(int first, int second)
{
if (first == second) return false;
if (first > second) return isPairLoop(second, first);
if (first == 0) return true;
int d = gcd(first, second);
return Integer.bitCount(first / d + second / d) != 1;
}
private static int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a % b);
}
Takes quadratic time on the number of digits on bigints.
Now you just have to prove that it works. I hope it works.
This question already has answers here:
Bitwise Multiply and Add in Java
(4 answers)
Closed 4 years ago.
So I have the following code to multiply two variables x and y using left and right shifts.
class Multiply {
public static long multiply(long x,long y) {
long sum = 0;
while(x != 0) {
if((x & 1) != 0) {
sum = sum+y;
}
x >>>= 1;
y <<= 1;
}
return sum;
}
public static void main(String args[]) {
long x = 7;
long y = 5;
long z = multiply(x,y);
}
}
But I dont understand the logic behind it, I understand that when you do
y<<=1
You are doubling y, but what does it mean that the number of iterations of the while loop depends on the number of bits x has?
while(x != 0)
Also why do I only sum if the rightmost bit of x is a 1?
if((x & 1) != 0) {
sum = sum+y;
}
I've really tried to understand the code but I haven't been able to get my head around the algorithm.
Those of us who remember from school how to multiply two numbers, each with two or more digits, will remember the algorithm:
23
x45
---
115
92x
----
1035
For every digit in the bottom factor, multiply it by the top factor and add the partial sums together. Note how we "shift" the partial sums (multiply them by 10) with each digit of the bottom factor.
This could apply to binary numbers as well. The thing to remember here is that no multiplication (by a factor's digit) is necessary, because it's either a 0 (don't add) or a 1 (add).
101
x110
-----
000
101
101
-----
11110
That's essentially what this algorithm does. Check the least significant bit; if it's a 1, add in the other factor (shifted), else don't add.
The line x >>>= 1; shifts right so that the next bit down becomes the least significant bit, so that the next bit can be tested during the next loop iteration. The number of loops depends on where the most significant bit 1 in x is. After the last 1 bit is shifted out of x, x is 0 and the loop terminates.
The line y <<= 1; shifts the other factor (multiplies by 2) in preparation for it be possibly added during the next loop iteration.
Overall, for every 1 bit in x at position n, it adds 2^n times y to the sum.
It does this without keeping track of n, but rather shuffling the bits x of 1 place right (dividing by 2) every iteration and shuffling the bits of y left (multiplying by 2).
Every time the 0 bit is set, which is tested by (x & 1) != 0, the amount to add is the current value of y.
Another reason this works are these equivalences:
(a + b) * y == a*y + b*y
x * y == (x/2) * (y*2)
which is the essence of what’s going on. The first equivalence allows bit-by-bit addition, and the second allows the opposite shuffling.
The >>> is an unsigned right shift which basically fills 0 irrespective of the sign of the number.
So for value x in the example 7 (in binary 111) the first time you do x >>>= 1; You are making the left most bit a zero so it changes from 111 to 011 giving you 3.
You do it again now you have 011 to 001 giving you 1
Once again and you have 001 to 000 giving you 0
So basically is giving you how many iterations before your number becomes zero. (Basically is diving your number in half and it is Integer division)
Now for the y value (5) you are adding it to your sum and then doubling the value of y
so you get:
y = 5 sum = 5
y = 10 sum = 15
y = 20 sum = 35
Only 3 iterations since x only needed to shift 3 times.
Now you have your result! 35
I'm trying to swap two ints - x and y in the example, and do it in one line without a library function.
So I started with this:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
y ^= x;
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
The output was 4, 3, 7, 3, 7, 4, 3, 4 as expected. All good so far.
Next up was this:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
y ^= (x ^= y);
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
The output was 4, 3, 7, 4, 3, 4 as expected once again. Still good so far.
Then finally this:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
x ^= (y ^= (x ^= y));
System.out.println(x);
System.out.println(y);
At this stage the output became 4, 3, 0, 4. Now I know that the 0 is a result of 4 ^ 4 because the x assignment wasn't complete at that time - why is this happening? Why doesn't the x ^= y actually assign 7 to the x variable so that it becomes 7 ^ 4 for the last assignment?
Let's try to expand your last expression.
It evaluates to,
x = x^(y = y^ (x = x^y));
Note that expressions are evaluated from left to right,
it becomes,
x = 4 ^ (y = 3 ^ (x = 4 ^ 3));
Now, the problem has become obvious. Right?
Edit:
To clear come confusion, let me try to explain what I mean by evaluating from left to right.
int i = 1;
s = i + (i = 2) + i;
Now, the expression will evaluate to,
s = 1 + 2 + 2;
Notice that i on the left of assignment was 1, but on the right of assignment (and on the assigment) was evaluated to 2, because the evaluation is from left to right, when it came to the 2nd and 3rd part of the expression, is value was 2.
The order of evaluation is defined in chapter 15 of the JLS. Item 15.7.1 says:
If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.
To explain further, they have two examples of computations that involve assignments. Here the assignment is on the left hand of the operator:
int i = 2;
int j = (i=3) * i;
System.out.println(j);
And they specifically say that the result is 9 and is not allowed to be 6. That is, the (i=3) is both calculated as 3 and i is assigned 3 before being multiplied with itself.
But in the second example:
int a = 9;
a += (a = 3); // first example
System.out.println(a);
int b = 9;
b = b + (b = 3); // second example
System.out.println(b);
The JLS specifies that both prints should produce 12, and are not allowed to produce 6. That is, because the assignment to b is on the right side, the value of the left b (or the implicit left a in the += operation), the value before that assignment is fetched and saved first, and only then the operation inside the parentheses is performed.
Internally, expressions are broken down into JVM operations that push and pop values onto an "operand stack". If you think about it like that - that in b = b + (b=3) The value of b is first pushed onto the operand stack, then the (b=3) is performed and its value is then added to the value popped from the stack (old value of b), it will make sense. At this point, the left hand b just stands for "What the value of b was when it was pushed on the stack" and not for the "current value of b".
Lets divide and compute.
The innermost parenthesis executes first and after all the parenthesis resolved, then the expression executes from left to right.
x ^= (y ^= (x ^= y)); // initial statement
x = x^(y = y^ (x = x^y)); //equals to
() have the highest precedence
x = x^(y = y^ (x = 3^4)); // first highest precedence ()
x = x^(y = y ^ (x = 7)); // still the first x is 3
x = 4 ^(y = 3 ^ (x = 7)); // now 3 ^ 7 =4
x = 4 ^ 4; // now 3 ^ 7 =4
x= 0;