Why is it that ~2 is equal to -3? How does
~ operator work?
Why is it that ~2 is equal to -3? How does
Remember that negative numbers are stored as the two's complement of the positive counterpart. As an example, here's the representation of -2 in two's complement: (8 bits)
The way you get this is by taking the binary representation of a number, taking its complement (inverting all the bits) and adding one. Two starts as 0000 0010, and by inverting the bits we get 1111 1101. Adding one gets us the result above. The first bit is the sign bit, implying a negative.
So let's take a look at how we get ~2 = -3:
Here's two again:
Simply flip all the bits and we get:
Well, what's -3 look like in two's complement? Start with positive 3: 0000 0011, flip all the bits to 1111 1100, and add one to become negative value (-3), 1111 1101.
So if you simply invert the bits in 2, you get the two's complement representation of -3.
The complement operator (~) JUST FLIPS BITS. It is up to the machine to interpret these bits.
c = 33 + ~n;
This calculates how many high order bits are remaining after using
n low order bits.
((x << c)>>c
This fills the high order bits with the same value as the sign bit of
!(blah ^ x)
This is equivalent to
blah == x
This looks like swapping a value using XOR. Though I am not sure about the strings in PHP (normally you use it for ints or something). For a truth table of XOR you can look here.
The interesting thing about
XOR is that it is reversable: A XOR B XOR B == A ... that is not working with
OR. Because of this fact, it can be used as in your example to swap two values:
$x ^= $y; $y ^= $x; $x ^= $y;
$x = $x ^ $y $y = $y ^ ($x ^ $y) // = $x $x = ($x ^ $y) ^ ($y ^ ($x ^ $y)) // = $y
Unary (such as
~) and binary operators in Java subject their operands to "unary numeric promotion" (JLS, Section 5.6.1) and "binary numeric promotion" (JLS, Section 5.6.2), respectively, fancy terms for "promote things to at least
Specifically, for unary numeric promotion, quoting the JLS section linked above:
Some operators apply unary numeric promotion to a single operand, which must produce a value of a numeric type:
... if the operand is of compile-time type byte, short, or char, it is promoted to a value of type int by a widening primitive conversion (§5.1.2).
(Binary numeric promotion is similar, operating on both operands.)
So, even if
b is a
~b is an
b's value was promoted to an
The solution: cast it back to a
b = (byte) (~b);
That leaves the question, why? It seems for the operators I can find, the JVM bytecode instructions for operating on
chars simply do not exist. For example, the unary bitwise complement operator you're using (~) is implemented as an "XOR" operation with
-1 (all bits set). From that link:
tempSpock &= ~mask;
25 iload_2 // Push local variable 2 (mask). 26 iconst_m1 // Push -1. 27 ixor // Bitwise EXCLUSIVE-OR top two ints: ~mask
However, I can only find instructions for XOR (and for other unary and binary operators too) for
double version exist for other operators where appropriate).
So, Java must perform those promotions because there are no bytecode instructions for performing those operations on
Why not, JVM?
That brings up another question: Why doesn't the JVM support such bytecode instructions? The answer appears to be, "Because there would be too many to encode them all in a one-byte instruction set." According to the JVM Specification, Section 2.11.1,
Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte. Instead, the instruction set of the Java Virtual Machine provides a reduced level of type support for certain operations. In other words, the instruction set is intentionally not orthogonal. Separate instructions can be used to convert between unsupported and supported data types as necessary.
In conclusion, the JVM's one-bytecode instruction set precludes the bytecode instructions for most operations on
shorts, necessitating unary numeric promotion and binary numeric promotion.
In C++ a boolean expression produces one of two values -
1. When you apply the unary minus
- to the result, you get
-1. When you re-interpret
uchar, you get
You can convert this expression to Java with a conditional:
dst[x] = (kHit >= kForeground) ? 255 : 0;
Because of branching, it is not going to be as fast as the original one. There's little you can do about the speed of it, however, as Java lacks abilities to re-interpret boolean values as numerics.