Let i
be a signed integer type. Consider
i += (i&-i);
i -= (i&-i);
where initially i>0
.
Source: setter's code of an online coding puzzle (w/o any explanation/comments).
++i will increment the value of i , and then return the incremented value. i = 1; j = ++i; (i is 2, j is 2) i++ will increment the value of i , but return the original value that i held before being incremented.
i+=i means the i now adds its current value to its self so let's say i equals 10 using this += expression the value of i will now equal 20 because you just added 10 to its self. i+=1 does the same as i=i+1 there both incrementing the current value of i by 1. 3rd January 2020, 3:15 AM.
The statement “i==1” evaluates to true if and only if the value of the variable “i” is equal to “1”. The statement “i&1” evaluates to true if and only if the “last bit in the binary form the variable 'i' is equal to '1'” i.e., “i” is an odd number.
Increment in java is performed in two ways, 1) Post-Increment (i++): we use i++ in our statement if we want to use the current value, and then we want to increment the value of i by 1. 2) Pre-Increment(++i): We use ++i in our statement if we want to increment the value of i by 1 and then use it in our statement.
The expression i & -i
is based on Two's Complement being used to represent negative integers. Simply put, it returns a value k
where each bit except the least significant non-zero bit of i
is set to 0
, but that particular bit keeps its own value. (i.e. 1
)
As long as the expression you provided executes in a system where Two's Complement is being used to represent negative integers, it would be portable. So, the answer to your second question would be that the expression is dependent on the representation of negative integers.
To answer your first question, since arithmetic expressions are dependent on the data types and their representations, I do not think that there is a solely arithmetic expression that would be equivalent to the expression i & -i
. In essence, the code below would be equivalent in functionality to that expression. (assuming that i
is of type int
) Notice, though, that I had to make use of a loop to produce the same functionality, and not just arithmetics.
int tmp = 0, k = 0;
while(tmp < 32)
{
if(i & (1 << tmp))
{
k = i & (1 << tmp);
break;
}
tmp++;
}
i += k;
On a Two's Complement architecture, with 4 bits signed integers:
| i | bin | comp | -i | i&-i | dec |
+----+------+------+----+------+-----+
| 0 | 0000 | 0000 | -0 | 0000 | 0 |
| 1 | 0001 | 1111 | -1 | 0001 | 1 |
| 2 | 0010 | 1110 | -2 | 0010 | 2 |
| 3 | 0011 | 1101 | -3 | 0001 | 1 |
| 4 | 0100 | 1100 | -4 | 0100 | 4 |
| 5 | 0101 | 1011 | -5 | 0001 | 1 |
| 6 | 0110 | 1010 | -6 | 0010 | 2 |
| 7 | 0111 | 1001 | -7 | 0001 | 1 |
| -8 | 1000 | 1000 | -8 | 1000 | 8 |
| -7 | 1001 | 0111 | 7 | 0001 | 1 |
| -6 | 1010 | 0110 | 6 | 0010 | 2 |
| -5 | 1011 | 0101 | 5 | 0001 | 1 |
| -4 | 1100 | 0100 | 4 | 0100 | 4 |
| -3 | 1101 | 0011 | 3 | 0001 | 1 |
| -2 | 1110 | 0010 | 2 | 0010 | 2 |
| -1 | 1111 | 0001 | 1 | 0001 | 1 |
Remarks:
i&-i
only has one bit set (it's a power of 2) and it matches the least significant bit set of i
.i + (i&-i)
has the interesting property to be one bit closer to the next power of two.i += (i&-i)
sets the least significant unset bit of i
.So, doing i += (i&-i);
will eventually make you jump to the next power of two:
| i | i&-i | sum | | i | i&-i | sum |
+---+------+-----+ +---+------+-----+
| 1 | 1 | 2 | | 5 | 1 | 6 |
| 2 | 2 | 4 | | 6 | 2 | -8 |
| 4 | 4 | -8 | |-8 | -8 | UB |
|-8 | -8 | UB |
| i | i&-i | sum | | i | i&-i | sum |
+---+------+-----+ +---+------+-----+
| 3 | 1 | 4 | | 7 | 1 | -8 |
| 4 | 4 | -8 | |-8 | -8 | UB |
|-8 | -8 | UB |
UB: overflow of signed integer exhibits undefined behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With