I need to compare two integer using Bit operator.
I faced a problem where I have to compare two integers without using comparison operator.Using bit operator would help.But how?
Lets say
a = 4;
b = 5;
We have to show a is not equal to b.
But,I would like to extend it further ,say,we will show which is greater.Here b is greater..
You need at least comparison to 0 and notionally this is what the CPU does for a comparison. e.g.
Equals can be modelled as ^ as the bits have to be the same to return 0
(a ^ b) == 0
if this was C you could drop the == 0 as this can be implied with
!(a ^ b)
but in Java you can't convert an int to a boolean without at least some comparison.
For comparison you usually do a subtraction, though one which handles overflows.
(long) a - b > 0 // same as a > b
subtraction is the same as adding a negative and negative is the same as ~x+1 so you can do
(long) a + ~ (long) b + 1 > 0
to drop the +1 you can change this to
(long) a + ~ (long) b >= 0 // same as a > b
You could implement + as a series of bit by bit operations with >> << & | and ^ but I wouldn't inflict that on you.
You cannot convert 1 or 0 to bool without a comparison operator like Peter mentioned. It is still possible to get max without a comparison operator.
I'm using bit (1 or 0) instead of int to avoid confusion.
bit msb(x):
return lsb(x >> 31)
bit lsb(x):
return x &1
// returns 1 if x < 0, 0 if x >= 0
bit isNegative(x):
return msb(x)
With these helpers isGreater(a, b) looks like,
// BUG: bug due to overflow when a is -ve and b is +ve
// returns 1 if a > b, 0 if a <= b
bit isGreater_BUG(a, b):
return isNegative(b - a) // possible overflow
We need two helpers functions to detect same and different signs,
// toggles lsb only
bit toggle(x):
return lsb(~x)
// returns 1 if a, b have same signs (0 is considered +ve).
bit isSameSigns(a, b):
return toggle(isDiffSigns(a, b))
// returns 1 if a, b have different signs (0 is considered +ve).
bit isDiffSigns(a, b):
return msb(a ^ b)
So with the overflow issue fix,
// returns 1 if a > b, 0 if a <= b
bit isGreater(a, b):
return
(isSameSigns(a, b) & isNegative(b - a)) |
(isDiffSigns(a, b) & isNegative(b))
Note that isGreater works correctly for inputs 5, 0 and 0, -5 also.
It's trickier to implement isPositive(x) properly as 0 will also be considered positive. So instead of using isPositive(a - b) above, isNegative(b - a) is used as isNegative(x) works correctly for 0.
Now max can be implemented as,
// BUG: returns 0 when a == b instead of a (or b)
// returns a if a > b, b if b > a
int max_BUG(a, b):
return
isGreater(a, b) * a + // returns 0 when a = b
isGreater(b, a) * b //
To fix that, helper isZero(x) is used,
// returns 1 if x is 0, else 0
bit isZero(x):
// x | -x will have msb 1 for a non-zero integer
// and 0 for 0
return toggle(msb(x | -x))
So with the fix when a = b,
// returns 1 if a == b else 0
bit isEqual(a, b):
return isZero(a - b) // or isZero(a ^ b)
int max(a, b):
return
isGreater(a, b) * a + // a > b, so a
isGreater(b, a) * b + // b > a, so b
isEqual(a, b) * a // a = b, so a (or b)
That said, if isPositive(0) returns 1 then max(5, 5) will return 10 instead of 5. So a correct isPositive(x) implementation will be,
// returns 1 if x > 0, 0 if x <= 0
bit isPositive(x):
return isNotZero(x) & toggle(isNegative(x))
// returns 1 if x != 0, else 0
bit isNotZero(x):
return msb(x | -x)
Using binary two’s complement notation
int findMax( int x, int y)
{
int z = x - y;
int i = (z >> 31) & 0x1;
int max = x - i * z;
return max;
}
Reference: Here
a ^ b = c // XOR the inputs
// If a equals b, c is zero. Else c is some other value
c[0] | c[1] ... | c[n] = d // OR the bits
// If c equals zero, d equals zero. Else d equals 1
Note: a,b,c are n-bit integers and d is a bit
The solution in java without using a comparator operator:
int a = 10;
int b = 12;
boolean[] bol = new boolean[] {true};
try {
boolean c = bol[a ^ b];
System.out.println("The two integers are equal!");
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
System.out.println("The two integers are not equal!");
int z = a - b;
int i = (z >> 31) & 0x1;
System.out.println("The bigger integer is " + (a - i * z));
}
I am going to assume you need an integer (0 or 1) because you will need a comparison to get a boolean from integer in java.
Here, is a simple solution that doesn't use comparison but uses subtraction which can actually be done using bitwise operations (but not recommended because it takes a lot of cycles in software).
// For equality,
// 1. Perform r=a^b.
// If they are equal you get all bits 0. Otherwise some bits are 1.
// 2. Cast it to a larger datatype 0 to have an extra bit for sign.
// You will need to clear the high bits because of signed casting.
// You can split it into two parts if you can't cast.
// 3. Perform -r.
// If all bits are 0, you will get 0.
// If some bits are not 0, then you get a negative number.
// 4. Shift right to extract MSB.
// This will give -1 (because of sign extension) for not equal and 0 for equal.
// You can easily convert it to 0 and 1 by adding 1 (I didn't include it in below function).
int equality(int a, int b) {
long r = ((long)(a^b)) ^0xffffffffl;
return (int)(((long)-r) >> 63);
}
// For greater_than,
// 1. Cast a and b to larger datatype to get more bits.
// You can split it into two parts if you can't cast.
// 2. Perform b-a.
// If a>b, then negative number (MSB is 1)
// If a<=b, then positive number or zero (MSB is 0)
// 3. Shift right to extract MSB.
// This will give -1 (because of sign extension) for greater than and 0 for not.
// You can easily convert it to 0 and 1 by negating it (I didn't include it in below function).
int greater_than(int a, int b) {
long r = (long)b-(long)a;
return (int)(r >> 63);
}
Less than is similar to greater but you swap a and b.
Trivia: These comparison functions are actually used in security (Cryptography) because the CPU comparison is not constant-time; aka not secure against timing attacks.
Related
Question
I was impressed by tricks like the xor-swap algorithm and similar. So I asked myself, is it possible to assign a variable a value, but only if the value is positive - without using any sort of if or hidden conditionals; just pure math.
Alternative
Basically, this but without the if:
int a = ...
int b = ...
if (b >= 0) {
a = b;
}
Examples
Here are some example input/output setups to illustrate the desired logic:
a = 1, b = 10 -> a = 10 // b is positive
a = 1, b = 0 -> a = 0 // b is 0, also positive
a = 1, b = -10 -> a = 1 // b is negative
tl;dr
int a = ...
int b = ...
int isNegative = b >>> 31; // 1 if negative, 0 if positive
int isPositive = 1 - isNegative; // 0 if negative, 1 if positive
a = isPositive * b + isNegative * a;
Signum
An easy way to achieve the task is to try to aquire some sort of signum, or more specifically a way to get a factor of
either 0, if b is positive
or 1 if b is negative, or vice-versa.
Now, if you take a look at how int is represented internally with its 32-bits (this is called Two's complement):
// 1234
00000000 00000000 00000100 11010010
// -1234
11111111 11111111 11111011 00101110
You see that it has the so called sign-bit on the very left, the most-significant-bit. Turns out, you can easily extract that bit with a simple bit-shift that just moves the whole bit-pattern 31 times to the right, only leaving the 32-th bit, i.e. the sign-bit:
int isNegative = b >>> 31; // 1 if negative, 0 if positive
Now, to get the opposite direction, you simply negate it and add 1 on top of it:
int isPositive = 1 - isNegative; // 0 if negative, 1 if positive
Annihilator and Identity
Once you have that, you can easily construct your desired value by exploiting the fact that
multiplication with 0 basically erases the argument (0 is an annihilator of *)
and addition with 0 does not change the value (0 is an identity element of +).
So, coming back to the logic we want to achieve in the first place:
we want b if b is positive
and we want a if b is negative
Hence, we just do b * isPositive and a * isNegative and add them together:
a = isPositive * b + isNegative * a;
Now, if b is positive, you will get:
a = 1 * b + 0 * a
= b + 0
= b
and if it is negative, you will get:
a = 0 * b + 1 * a
= 0 + a
= a
Other datatypes
The same approach can also be applied to any other signed data type, such as byte, short, long, float and double.
For example, here is a version for double:
double a = ...
double b = ...
long isNegative = Double.doubleToLongBits(b) >>> 63;
long isPositive = 1 - isNegative;
a = isPositive * b + isNegative * a;
Unfortunately, in Java you can not use >>> directly on double (since it usually also makes no sense to mess up the exponent and mantissa), but therefore you have the helper Double#doubleToLongBits which basically reinterprets the double as long.
Looking at |, it is described as a bitwise operator OR.
So, in this code example:
private int getColorRGB(int color) { // 255255255 would be white, 000255000 green, etc.
if (color < 0) return -1;
int r = color / 1000000 % 1000;
int g = color / 1000 % 1000;
int b = color % 1000;
if (r > 255 || g > 255 || b > 255) throw new IllegalArgumentException("RGB values cannot exceed 255.");
return (r >> 16) | (g >> 8) | b; // POINT OF INTEREST
}
I can replace the 2 | at the line marked with POINT OF INTEREST with +, and I still get the same output.
The method takes an int rrrgggbbb, so 255 would be blue, 200200200 would be light gray, etc.
So, my question is; what is the difference between the two
a = 2; // binary 0x10
b = 2; // binary 0x10
c = a + b; // c = 4
c = a | b; // c = 2
| is a bit operation and it doesn't equals +
Sometimes it gives the same result: 2+1 and 2|1 for example; but it isn't a rule
| takes the bitwise OR means takes the greater corresponding bit of the two numbers while + takes the addition of the two corresponding bits and takes further carries which means 1+1 gives us as 10 while 1|1 will stops only to 1. | will never cause out of range if larger argument is in range while + can have out or range if if sum of both causes a number out of range.
If in two numbers, corresponding bits are different, then only in that case | acts as + because during summation, carries never produces.
Remember | and + are 2 different operators. That being said, sometimes they can have the same result, like 1*1 and 1/1. While they have the same result, they do not go through the same process.
Here is the reference implementation I got, the confusion is, I think there is no need for recursion. I post both reference code and my thought below here, for the difference see line 5.
Any insights are appreciated. Please feel free to correct me if I am wrong.
Reference implementation:
1 int add_no_arithm(int a, int b) {
2 if (b == 0) return a;
3 int sum = a ^ b; // add without carrying
4 int carry = (a & b) << 1; // carry, but don’t add
5 return add_no_arithm(sum, carry); // recurse
6 }
Another implementation in my thought,
1 int add_no_arithm(int a, int b) {
2 if (b == 0) return a;
3 int sum = a ^ b; // add without carrying
4 int carry = (a & b) << 1; // carry, but don’t add
5 return sum ^ carry;
6 }
BTW, tried 8+8 in Python - worked for me:
Is the recursion needed?
a = 8
b = 8
sum = a ^ b
carry = (a & b) << 1
print(sum^carry) # 16
The second approach doesn't work with 1 + 3.
Here are the steps
a == 01
b == 11
sum = a^b == 10
carry = (a&b) << 1 == 10
sum ^ carry == 00 // wrong answer! 1 + 3 == 4
Just doing ^ at the last step is not enough, as there may be a carry in that sum.
The question is, whether recursive is needed?
Yes, it is. You can see this for yourself by experimenting with other numbers, instead of just 8 + 8. For example, try 21 and 15, without recursion this gives output of 26.
The bitwise XOR operator ^ is only equivalent to the addition operator + if there is no binary carrying in the sums. If there is binary carrying, then they are not equivalent. For example, 8 + 7 equals 8 ^ 7 equals 15, but 8 + 8 is 16 while 8 ^ 8 is 0.
Even if you have calculated the sum-no-carry and the carry-no-sum correctly, what if those two numbers, when added, would produce a binary carry? Then your ^ operator at the end would be incorrect. Without the + operator, the only option I see is to recurse, to add those numbers. This will recur until one of the numbers is 0.
Example:
add(no_arithm(18, 6))
sum = a^b 18 ^ 6 is 20.
carry = (a & b) << 1 18 & 6 is 2, bit shift left 1 is 4.
return sum ^ carry 20 ^ 4 is 16, incorrect (18 + 6 = 24).
Will this work?
import java.util.*;
public class Solution {
public static int sumOfTwoNumbers(int a, int b) {
if (b<0){
for(int j = 1; j<=-b;j++)
--a;
}
if(b>0){
for (int i = 1; i <= b; i++){
a++;
}
}
return a;
}
Question is based on this site.
Could someone explain the meaning of these lines:
private int getBitValue(int n, int location) {
int v = n & (int) Math.round(Math.pow(2, location));
return v==0?0:1;
}
and
private int setBitValue(int n, int location, int bit) {
int toggle = (int) Math.pow(2, location), bv = getBitValue(n, location);
if(bv == bit)
return n;
if(bv == 0 && bit == 1)
n |= toggle;
else if(bv == 1 && bit == 0)
n ^= toggle;
return n;
}
int v = n & (int) Math.round(Math.pow(2, location));
Math.pow(2, location) raises 2 to the given power. This is rounded and converted to an integer. In binary, this will be 00000001 if location==0, 00000010 if location==1, 00000100 if location==2, etc. (Much better would be 1 << location which shifts a "1" by a certain number of bits, filling in 0 bits at the right. Using Math.pow will probably try to compute the logarithm of 2 every time it's called.)
n & ... is a bitwise AND. Since the item on the right has just one bit set, the effect is to zero out every bit in n except for that one bit, and put the result in v. This means that v will be 0 if that one bit is 0 in n, and something other than 0 if that bit is `, which means
return v==0?0:1;
returns 0 if the bit is clear and 1 if it's set.
int toggle = (int) Math.pow(2, location), bv = getBitValue(n, location);
toggle is set to that Math.pow thing I already described. bv is set to the bit that's already in n, which is 0 or 1. If this equals the thing you're setting it to, then we don't need to do anything to n:
if(bv == bit)
return n;
Otherwise, either we need to set it to 1 (remember that toggle will have just one bit set). n |= toggle is the same as n = n | toggle. | is a bit-wise OR, so that one bit will be set in n and all other bits in n will remain the same"
if(bv == 0 && bit == 1)
n |= toggle;
Or we need to set the bit to 0. n ^= toggle is the same as n = n ^ toggle. n is an exclusive OR. If we get here, then the bit in n is 1, and the bit in toggle is 1, and we want to set the bit in n to 0, so exclusive OR will change that bit to 0 while leaving every other bit the same:
else if(bv == 1 && bit == 0)
n ^= toggle;
The getBitValue just gets the value of a specified bit (on a certain location)
The setBitValue sets the value of a bit on the matched specific location.
These getter/setter methods are usually used for image processing, i.e. if you have a musk and you want to change a specific bit value.
Nothing more or less.
Given two integers a and b, how can we check that b is a rotated version of a?
For example if I have a = 0x01020304 (in binary 0000 0001 0000 0010 0000 0011 0000 0100), then the following b values are correct:
...
0x4080C1 (right-rotated by 2)
0x810182 (right-rotated by 1)
0x2040608 (left-rotated by 1)
0x4080C10 (left-rotated by 2)
...
For n bit numbers you can use KMP algorithm to search b inside two copies of a with complexity O(n).
In C++, without string conversion and assuming 32 bits int:
void test(unsigned a, unsigned b)
{
unsigned long long aa = a | ((unsigned long long)a<<32);
while(aa>=b)
{
if (unsigned(aa) == b) return true;
aa>>=1;
}
return false;
}
i think you have to do it in a loop (c++):
// rotate function
inline int rot(int x, int rot) {
return (x >> rot) | (x << sizeof(int)*8 - rot));
}
int a = 0x01020304;
int b = 0x4080C1;
bool result = false;
for( int i=0; i < sizeof(int)*8 && !result; i++) if(a == rot(b,i)) result = true;
In the general case (assuming arbitrary-length integers), the naive solution of consisting each rotation is O(n^2).
But what you're effectively doing is a correlation. And you can do a correlation in O(n log n) time by going via the frequency domain using an FFT.
This won't help much for length-32 integers though.
By deriving the answers here, the following method (written in C#, but shall be similar in Java) shall do the checking:
public static int checkBitRotation(int a, int b) {
string strA = Convert.ToString(a, 2).PadLeft(32, '0');
string strB = Convert.ToString(b, 2).PadLeft(32, '0');
return (strA + strA).IndexOf(strB);
}
If the return value is -1, b is not rotated version of a. Otherwise, b is rotated version of a.
If a or b is a constant (or loop-constant), you can precompute all rotations and sort them, and then do a binary search with the one that isn't a constant as key. That's fewer steps, but the steps are slower in practice (binary search is commonly implemented with a badly-predicted branch), so it might not be better.
In the case that it's really a constant, not a loop-constant, there are some more tricks:
if a is 0 or -1, it's trivial
if a has only 1 bit set, you can do the test like b != 0 && (b & (b - 1)) == 0
if a has 2 bits set, you can do the test like ror(b, tzcnt(b)) == ror(a, tzcnt(a))
if a has only one contiguous group of set bits, you can use
int x = ror(b, tzcnt(b));
int y = ror(x, tzcnt(~x));
const int a1 = ror(a, tzcnt(a)); // probably won't compile
const int a2 = ror(a1, tzcnt(~a1)); // but you get the idea
return y == a2;
if many rotations of a are the same, you may be able to use that to skip certain rotations instead of testing them all, for example if a == 0xAAAAAAAA, the test can be b == a || (b << 1) == a
you can compare to the smallest and biggest rotations of the constant for a quick pre-test, in addition to the popcnt test.
Of course, as I said in the beginning, none of this applies when a and b are both variables.
I would use Integer.rotateLeft or rotateRight func
static boolean isRotation(int a, int b) {
for(int i = 0; i < 32; i++) {
if (Integer.rotateLeft(a, i) == b) {
return true;
}
}
return false;
}