Reputation: 3418
Can someone explain how the heck below function increments:
function increment (i) {
i ^= (i & ~-~i) | (~i & -~i)
return i
}
I think I know javascript, but when I see something above, it pisses me off.
Upvotes: 2
Views: 115
Reputation: 64904
Here's a shorter proof, automatically generated by my website
i ^ (i & ~-~i | ~i & -~i)
definition of xor
i ^ i ^ -~i
xor with self
-~i
definition of two's complement
~~i + 1
double complement
i + 1
In the step "definition of xor", the definition x ^ y = x & ~y | ~x & y
is used, with x
being i
and y
being -~i
.
In the step "definition of two's complement", the definition -x = ~x + 1
is used, with x
being ~i
.
Upvotes: 2
Reputation: 33046
Boolean algebra 101.
First, under the assumption that we are working with two's complement, this is the definition of unary minus operator -
(see the footnote too):
-A = ~A + 1
Here is your RHS expression, with some extra parenthesis added, without the shortcut assignment and with all operators in extended form for better readability:
i xor ((i and ~(-(~i))) or (~i and -(~i))
We apply the first relation:
i xor ((i and ~(~~i + 1)) or (~i and (~~i + 1))
complement operator ~
is idempotent, meaning that ~~i
is equal to i
, so we simplify:
i xor ((i and ~(i + 1)) or (~i and (i + 1)))
the second term of the xor
operator has the (X and ~Y) or (~X and Y)
form, which means "one of X and Y must be true for the expression to be true, but not both", which the very definition of exclusive or (xor
), so we can replace that with X xor Y
, obtaining:
i xor (i xor (i + 1))
we change the association (xor
is associative) and we get:
(i xor i) xor (i + 1)
i xor i
is a contradiction (always false
), so we get:
false xor (i + 1)
note that the truth value of false xor X
depends entirely on X
, so we can rewrite the above as:
i + 1
So the RHS evaluates to i + 1
. We replace it in the original code and we get:
function increment(i) {
i = i + 1
return i
}
Voilà!
NOTE: +
should be formalized as another operator if we wanted to be fully formal. In this case, we can safely skip the definition and keep it a black box, since we did not need any of its properties. The only thing that matters is that ~
has a higher priority than +
.
Upvotes: 5