Understanding the arithmetic in `(1 << j) - 1` - bit-manipulation

Would appreciate help in explaining the following bit operation. Pardon my lack of understanding of bit arithmetic.
int max = ~0;
int left = max - ((1 << j) - 1);
What will be the result of this operation? Is (1<<(j-1)) equivalent to ((1 << j) - 1)?

Follow the below formulas,
Case : 1
(1 << j) - 1) is equal to 2^j-1 [j = 1,2...]
Case : 2
(1<<(j-1)) is equal to 2^(j-1) [j = 1,2,3...]
Is (1<<(j-1)) equivalent to ((1 << j) - 1)?
No, Obviously from above formulas.
What will be the result of this operation?
For this question, max will be "-1" [bitwise NOT(0) is equivalent to complement of all bit values of 0]
then formula will be
left = -(2j)
If j = -1 or j = 0, then the above formulas won't work as expected, because 1<<-1 is undefined behavior in C. More details found at below links.
https://stackoverflow.com/a/4945765/3979414
http://c0x.coding-guidelines.com/6.5.7.html

(1 << j) - 1 is a number with j one bits on the right
j bits
┌──────┐
00...0011...111
max is a number with all one bits
11...1111...111
Each one bit from max will become 0 when subtracting from the one bit from (1 << j) - 1, and remain 1 otherwise. Hence max - ((1 << j) - 1) will produce a value with j zero bits on the right
j...210 ← bit position
11...1111...11
- 00...0011...11
──────────────────
11...1100...00
That means the result is the bitwise not of (1 << j) - 1, i.e.
max - ((1 << j) - 1) == ~((1 << j) - 1)
Is (1<<(j-1)) equivalent to ((1 << j) - 1)?
1 << (j-1) shifts 1 j-1 places to the left and produces 2j - 1, so it has j-1 zeros on the right followed by a one 100...00. (1 << j) - 1 gives a number with j zeros on the right which is 2j - 1, as said above. Can you guess they're similar or not?

Related

Algorithm : partial grid count problme

In partial grid count problem
Each point is marked with 1 or 0. In this case, the problem of finding the number of subgrid with 1 in all four corners
Each row is expressed in bitset form, and while searching each row, the count is added when the common column is painted by comparison with the and operation.
Finally,count(count-1)/2 the sublattice where the first row is a and the last row is b.
I don't understand how to get the number of sublattices with the formula count(count-1)/2.
bitset<5> row[5];
row[0] = (1 << 3) + (1 << 0);
row[1] = (1 << 3) + (1 << 2);
row[2] = (1 << 4);
row[3] = (1 << 3) + (1 << 2) + (1 << 0);
row[4] = 0;
int count = 0;
for (int a = 0; a < 4; a++) {
for (int b = a + 1; b < 5; b++) {
int count_row = (row[a] & row[b]).count();
count += count_row;
}
}
count = count * (count - 1) / 2;
The meaning of the formula N*(N-1)/2 is the sum of all numbers from 1 to N.
If you look at a row e.g. 0001110000000000, then there will be sub sets
1, 11, 111, the sum of those is 1+2+3, i.e. the sum of all numbers 1 to 3.
I think that is what the text means.
However, that only counts the subsets which start on the left, not counting the middle single 1 and the right single 1 and the right 11.
So I think I know what the text means - but think it is wrong.

Is there a way to optimise the Collatz conjecture into a branchless algorithm?

I'm trying to create an algorithm that will compute the collatz conjecture, this is the code so far:
while (n > 1) {
n % 2 == 0 ? n /= 2 : n = n * 3 + 1;
}
I was wondering if there was a way to optimize this any further since efficiency and speed is crucial for this, and I've heard about branchless programming but I'm not sure how to implement it, or if it's worth it to begin with.
Sure. You need the loop, of course, but the work inside can be done like this:
n /= (n&-n); // remove all trailing 0s
while(n > 1) {
n = 3*n+1;
n /= (n&-n); // remove all trailing 0s
}
It also helps that this technique does all the divisions by 2 at once, instead of requiring a separate iteration for each of them.
One way to make it branchless (except for the loop condition) is to multiply n / 2 with the n % 2 == 0 result (1 for true) and multiply (n * 3 + 1) with the negated result of (n % 2 == 0) and add them together.
void collatz(unsigned long long n) {
std::cout << n << '\n';
while (n > 1) {
auto m = n % 2 == 0;
n = m * (n / 2) + !m * (n * 3 + 1);
std::cout << n << '\n';
}
}
Demo

C++. Logical expression

I am trying to solve the following task. Given an integer x, I want to compute 2 numbers (a and b) which are:
1) divisible by 2 or 3 (e.g a % 2 == 0 or a % 3 == 0 )
2) x = a +
b
I wrote the following code, to find such a and b.
cin >> x;
if (x % 2 == 0) {
a = b = x / 2;
} else {
a = x / 2;
b = a + 1;
}
while((a % 3 !=0 || a % 2 != 0) && (b % 2 != 0 || b % 3 != 0)) {
a++;
b--;
}
However it does not work. For example when x is 13, it prints out that a = 6 and b = 7. But 7 is not divisible by 2 or 3. What is the problem ?
Examine your continuation condition carefully (where n is some arbitrary integer, possibly different in each use so, for example a != 3n simply means that a is not a multiple of three). I'll show the process:
while((a % 3 != 0 || a % 2 != 0) && (b % 2 != 0 || b % 3 != 0))
( a != 3n OR a != 2n ) AND ( b != 2n OR b != 3n )
( a != 6n ) AND ( b != 6n )
It says: continue while both a is not a multiple of both two and three, and b is not a multiple of both two and three. In other words, it will only continue if both a and b are multiples of six. On the flip side of that, it will of course exit if either a or b is not a multiple of six.
Since an input value of 13 sets a = 6 and b = 7, the continuation case is false on the first iteration (seven is not a multiple of six).
Perhaps it would be better to rethink the way you figure out whether certain number combinations are valid(a). For example (assuming the numbers have to be between 1 and N - 1 since, otherwise, your solution space is likely to be infinite), you could use something like:
#include <iostream>
int main() {
// Get the number.
int num;
std::cout << "Number? ";
std::cin >> num;
// Check all i + j = n for 1 <= i,j < n.
for (int i = 1, j = num - 1; i < j; ++i, --j) {
// Disregard if either number not a multiple of 2 or 3.
if ((i % 2) != 0 && (i % 3) != 0) continue;
if ((j % 2) != 0 && (j % 3) != 0) continue;
std::cout << num << " => " << i << ", " << j << "\n";
return 0;
}
std::cout << num << " => no solution\n";
return 0;
}
Note my use of i < j is the for continuation condition, this is assuming they have to be distinct numbers. If they're allowed to be the same number, change that to i <= j.
(a) Using all of and, or, and not (even implicitly, by the reversal of continuation and exit conditions), is sometimes more trouble than it's worth since De Morgan's theorems tend to come into play:
_____ _ _
A ∩ B ⇔ A ∪ B : (not(A and B)) is ((not A) or (not B))
_____ _ _
A ∪ B ⇔ A ∩ B : (not(A or B)) is ((not A) and (not B))
In cases like that, code can become more readable if you break out the individual checks.
Interestingly, if you run that code with quite a few input values, you'll see the pattern that, if a solution exists, one of the numbers in that solution is always two or three.
That's because, other than the pathological cases of sums less than five (or less than four if the solution is allowed to have identical numbers):
every even number 2n, n > 1 is the sum of 2 and 2n - 2, both multiples of two (2n - 2 = 2(n - 1)); and
every odd number 2n + 1, n > 2 is the sum of 3 and 2n + 1 - 3, the first a multiple of three and the second a multiple of two (2n + 1 - 3 = 2n - 2 = 2(n - 1)).
So, in reality, no loop is required:
if (num < 5) { // 4 if allowing duplicates.
std::cout << num << " => no solution\n";
} else {
int first = (num % 2) == 0 ? 2 : 3;
std::cout << num << " => " << first << ", " << (num - first) << "\n";
}
This actually gives a different result for some numbers, such as 17 = 2 + 15 = 3 + 14 but both solutions are still correct.

Creating a mask around a subsection [i,j] for a number [duplicate]

This question already has answers here:
Fastest way to produce a mask with n ones starting at position i
(5 answers)
Closed 3 years ago.
I'm learning bit manipulation and bitwise operators currently and was working on a practice problem where you have to merge a subsection[i,j] of an int M into N at [i,j]. I created the mask in a linear fashion but after googling i found that ~0 << j | ((1 << i) - 1) creates the mask I wanted. However, I am not sure why. If anyone could provide clarification that would great, thanks.
void merge(int N, int M, int i, int j){
int mask = ~0 << j | ((1 << i) - 1);
N = N & mask; // clearing the bits [i,j] in N
mask = ~(mask); // inverting the mask so that we can isolate [i,j] in
//M
M = M & mask; // clearing the bits in M outside of [i,j]
// merging the subsection [i,j] in M into N at [i,j] by using OR
N = N | M;
}
~0 is the "all 1 bits" number. When you shift it up by j, you make the least significant j bits into 0:
1111111111111111 == ~0 == ~0 << 0
1111111111111110 == ~0 << 1
1111111111100000 == ~0 << 5
1111111110000000 == ~0 << 7
1 << i is just the i + 1th least significant bit turned on.
0000000000000001 == 1 << 0
0000000000000010 == 1 << 1
0000000000001000 == 1 << 3
0000000001000000 == 1 << 6
When you subtract 1 from this, there is a one carried all the way from the left, so you are left with all the bits before the 1 bit becoming 1 (So you end up with the first i least significant bits turned on).
0000000000000000 == (1 << 0) - 1
0000000000000001 == (1 << 1) - 1
0000000000000111 == (1 << 3) - 1
0000000000111111 == (1 << 6) - 1
When you or them, you end up with a window between the jth least significant bit and the i + 1th least significant bit turned on (inclusive).
1111111110000000 == ~0 << 7
0000000000000111 == (1 << 3) - 1
1111111110000111 == ~0 << 7 | ((1 << 3) - 1)
7 3
When you & a number with this mask, you clear the bits in the range (i, j] (The ith bit itself is not included).
When you ~ the mask, you get a new mask that will only give you the bits in the range (i, j].
1111111110000111 == ~0 << 7 | ((1 << 3) - 1)
0000000001111000 == ~(~0 << 7 | ((1 << 3) - 1))
Which could also be constructed with something like ((1 << j) - 1) & ~((1 << i) - 1).

Operators evaluation

This code evaluates to true:
#include <iostream>
int main(){
int x = 9;
int j = x-1;
if(x - j+1 > 1)
std::cout << "Ehhhh???\n";
}
But this one to false:
#include <iostream>
int main(){
int x = 9;
int j = x-1;
if(x - (j+1) > 1)
std::cout << "Ehhhh???\n";
}
plus and minus operators has higher precedence than "<", I'm also using only one data type so there should be bo overflow. Why results are different?
This is really just a matter what value the 1 gets added to. Addition and subtraction have left to right associativity so we start from the left and work our way right.
x - j + 1
(9 - 8) + 1
1 + 1
2
Where as
x - (j + 1)
9 - (8 + 1)
9 - 9
0
Forces the addition to be attached to j instead of x-j so the second case is rightly false.
Since the precedence of arithmetic + and - is the same but the associativity is from left to right, the one without the parenthesis will first do the subtraction then the addition, i.e.:
x - j+1 ==2 //here the operation is performed from left to right,subtraction first then addition
x - (j+1)==0 //here the one inside the parenthesis will be done first,i.e addition first then subtraction
Mathematically you have 2 different expressions:
x - j + 1 is equal to x - ( j - 1 )
and
x - ( j + 1 ) is equal to x - j - 1