Java makes use of the “two’s complement” for representing signed numbers
When studying Java and I first heard that the very first (left-to-right) bit was for the number sign, I thought that the other bits following would be the same for positives and negatives, I mean, if the binary “00001111” would result to the decimal 15, so “10001111” would then result to “-15”. But it wouldn’t, and just because it makes use of “two’s complement”.
It’s called “two’s complement” because the sum operation over the positive with its negative represented bits (of a corresponding decimal) always results zero.
To illustrate it, let’s assume the decimal value “3”, which represented on a 3 bit length results to; “011”
The negative decimal value, in this case “-3”, on a 3 bit length representation, results to (I’m going to explain why); “101”
The main goal for “two’s complement” is to decrease the complexity for mathematical operations with bits, and in the case above, if we do the calc below;
0 1 1
+
1 0 1
_______
1 0 0 0
… we endup with the binary “1000” but it is 4 bit length, and our representation is only 3 bit length, so we get from it the only three last bits (the very first is thrown away, once we cannot represent it cause we don’t have enough space =]) in this case “000”.
And it worked, the decimal operation “3 + (-3) = 0” which can be represented as binary “011 + 101 = 000”
At first glance it looks strange, right?
The rule for getting the binary representation “of a corresponding two’s complement” for a given decimal value, is, applying “2 ^ nBits - decimalValue = decimalTwosComplement”.
Example 1
Given the decimal “3” on a 3 bit length representation, we have the binary “011” and then we apply “2 ^ 3 - 3” which equals 5, that its binary representation is “101”, and that’s it, the negative decimal “-3” in binary representation is “101” in “two’s complement”.
3 bits
3 (dec) => 011 (bin)
-3 (dec) => 101 (bin)
Example 2
Given the decimal “12” on a 8 bit length (a Java byte primitive data type), we have the binary “00001100” and then we apply “2 ^ 8 - 12” which equals 244 (decimal) represented by the binary “11110100” that then represents a “-12” decimal value.
8 bits (a byte)
12 (dec) => 00001100 (bin)
-12 (dec) => 11110100 (bin)
Note: It was already told, but it is worth to mention that the very first bit represents the sign, and if it is “0” so it is a positive decimal number, otherwise, if it is “1” then it represents a negative decimal number.
Example 3
In case someone gives the binary “00001111”, how to get the corresponding decimal representation, considering the two’s complement?
Answering; It represents a positive decimal value, since the very first bit is “0”, so a basic transformation “binary-to-decimal” can be applied, thus getting the decimal 15.
Example 4
If it’s given a negative decimal value, the calc to get its corresponding binary representation is very similar to get it from a positive one. “2 ^ nBits - |negativeDecimal|”
… So then get the binary from the resulting decimal.
In case someone gives the decimal “-15” we do;
2 ^ 8 - |-15| => 256 - 15 => 241
… which applying the basic “decimal-to-binary” transformation, from the decimal 241 we get “11110001”
8 bits (a byte)
15 (dec) => 00001111
-15 (dec) => 11110001
Example 5
In case someone gives the binary “10001111”, how to get the corresponding decimal representation, considering the two’s complement?
Answering; It gives us the clue that it represents a negative decimal value, so we need first get its “decimal two’s complement” applying the basic “binary-to-decimal” transformation.
i.e; 10001111 => 143
… so now we need apply the formula “ - |2 ^ nBits - decimalValue = decimalTwosComplement|”;
-|2 ^ 8 - decimalValue = 143| => -|256 - 143 = decimalValue|=>-|256–143 = decimal| => -|113 = decimalValue|=>-113
That’s it for now!