Two's complement of a fixed-width binary number X is a binary number that you get by inverting X's binary digits and adding one, discarding possible overflow.
twos_compl(X){ return ~X+1; }
E.g., for 4-bit wide numbers:
X ~X ~X+1
0000 1111 0000
0001 1110 1111
0010 1101 1110
0011 1100 1101
If a computer architectures uses two's complement to represent mathematically negated signed numbers, i.e., if twos_compl(X) == -X
, then certain math operations become easy to implement.
(In such a representation of a signed number the highest bit then means -pow(2,bit_index_from_the_right)
rather than the usual (usual for unsigned numbers and for every other bit in a signed two's complement representation) +pow(2,bit_index_from_the_right)
.)
For example, addition (or subtraction) on an architecture that uses two's complement representation for negative numbers will use the same instruction as the corresponding unsigned addition (or subtraction respectively), and it will work regardless of the sign of the operands.
In C on a two's complement platform:
int sadd(int A, int B) { return A+B; }
unsigned uadd(unsigned A, unsigned B) { return A+B; }
will compile to the same instruction.
And by definition of two's complement, so will:
int neg(int A) { return -A; }
and
int neg2(int A) { return ~A+1; }
So to summarize, two's complement isn't necessarily mathematical negation—it is a transformation of the binary representation of a number that a computer architecture may interpret as negation and if it does, it simplifies math on that computer architecture.