Related
I am trying to understand how Java stores integer internally. I know all java primitive integers are signed, (except short?). That means one less bit available in a byte for the number.
My question is, are all integers (positive and negative) stored as two's complement or are only negative numbers in two's complement?
I see that the specs says x bit two's complement number. But I often get confused.
For instance:
int x = 15; // Stored as binary as is? 00000000 00000000 00000000 00001111?
int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010
Edit
To be clear, x = 15
In binary as is: `00000000 00000000 00000000 00001111'
Two's complement: `11111111 11111111 11111111 11110001`
So if your answer is all numbers are stored as two's complement then:
int x = 15; // 11111111 11111111 11111111 11110001
int y = -22 // 11111111 11111111 11111111 11101010
The confusion here again is the sign says, both are negative numbers. May be I am misreading / misunderstanding it?
Edit
Not sure my question is confusing. Forced to isolate the question:
My question precisely: Are positive numbers stored in binary as is while negative numbers are stored as two's complement?
Some said all are stored in two's complement and one answer says only negative numbers are stored as two's complement.
Let's start by summarizing Java primitive data types:
byte: Byte data type is an 8-bit signed two's complement integer.
Short: Short data type is a 16-bit signed two's complement integer.
int: Int data type is a 32-bit signed two's complement integer.
long: Long data type is a 64-bit signed two's complement integer.
float: Float data type is a single-precision 32-bit IEEE 754 floating point.
double: double data type is a double-precision 64-bit IEEE 754 floating point.
boolean: boolean data type represents one bit of information.
char: char data type is a single 16-bit Unicode character.
Source
Two's complement
"The good example is from wiki that the relationship to two's complement is realized by noting that 256 = 255 + 1, and (255 − x) is the ones' complement of x
0000 0111=7 two's complement is 1111 1001= -7
the way it works is the MSB(the most significant bit) receives a negative value so in the case above
-7 = 1001= -8 + 0+ 0+ 1
Positive integers are generally stored as simple binary numbers (1 is 1, 10 is 2, 11 is 3, and so on).
Negative integers are stored as the two's complement of their absolute value. The two's complement of a positive number is when using this notation a negative number.
Source
Since I received a few points for this answer, I decided to add more information to it.
A more detailed answer:
Among others there are four main approaches to represent positive and negative numbers in binary, namely:
Signed Magnitude
One's Complement
Two's Complement
Bias
1. Signed Magnitude
Uses the most significant bit to represent the sign, the remaining bits are used to represent the absolute value. Where 0 represents a positive number and 1 represents a negative number, example:
1011 = -3
0011 = +3
This representation is simpler. However, you cannot add binary numbers in the same way that you add decimal numbers, making it harder to be implemented at the hardware level. Moreover, this approach uses two binary patterns to represent the 0, -0 (1000) and +0 (0000).
2. One's Complement
In this representation, we invert all the bits of a given number to find out its complementary. For example:
010 = 2, so -2 = 101 (inverting all bits).
The problem with this representation is that there still exist two bits patterns to represent the 0, negative 0 (1111) and positive 0 (0000)
3. Two's Complement
To find the negative of a number, in this representation, we invert all the bits and then add one bit. Adding one bit solves the problem of having two bits patterns representing 0. In this representation, we only have one pattern for
0 (0000).
For example, we want to find the binary negative representation of 4 (decimal) using 4 bits. First, we convert 4 to binary:
4 = 0100
then we invert all the bits
0100 -> 1011
finally, we add one bit
1011 + 1 = 1100.
So 1100 is equivalent to -4 in decimal if we are using a Two's Complement binary representation with 4 bits.
A faster way to find the complementary is by fixing the first bit that as value 1 and inverting the remaining bits. In the above example it would be something like:
0100 -> 1100
^^
||-(fixing this value)
|--(inverting this one)
Two's Complement representation, besides having only one representation for 0, it also adds two binary values in the same way that in decimal, even numbers with different signs. Nevertheless, it is necessary to check for overflow cases.
4. Bias
This representation is used to represent the exponent in the IEEE 754 norm for floating points. It has the advantage that the binary value with all bits to zero represents the smallest value. And the binary value with all bits to 1 represents the biggest value. As the name indicates, the value is encoded (positive or negative) in binary with n bits with a bias (normally 2^(n-1) or 2^(n-1)-1).
So if we are using 8 bits, the value 1 in decimal is represented in binary using a bias of 2^(n-1), by the value:
+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
Java integers are of 32 bits, and always signed. This means, the most significant bit (MSB) works as the sign bit. The integer represented by an int is nothing but the weighted sum of the bits. The weights are assigned as follows:
Bit# Weight
31 -2^31
30 2^30
29 2^29
... ...
2 2^2
1 2^1
0 2^0
Note that the weight of the MSB is negative (the largest possible negative actually), so when this bit is on, the whole number (the weighted sum) becomes negative.
Let's simulate it with 4-bit numbers:
Binary Weighted sum Integer value
0000 0 + 0 + 0 + 0 0
0001 0 + 0 + 0 + 2^0 1
0010 0 + 0 + 2^1 + 0 2
0011 0 + 0 + 2^1 + 2^0 3
0100 0 + 2^2 + 0 + 0 4
0101 0 + 2^2 + 0 + 2^0 5
0110 0 + 2^2 + 2^1 + 0 6
0111 0 + 2^2 + 2^1 + 2^0 7 -> the most positive value
1000 -2^3 + 0 + 0 + 0 -8 -> the most negative value
1001 -2^3 + 0 + 0 + 2^0 -7
1010 -2^3 + 0 + 2^1 + 0 -6
1011 -2^3 + 0 + 2^1 + 2^0 -5
1100 -2^3 + 2^2 + 0 + 0 -4
1101 -2^3 + 2^2 + 0 + 2^0 -3
1110 -2^3 + 2^2 + 2^1 + 0 -2
1111 -2^3 + 2^2 + 2^1 + 2^0 -1
So, the two's complement thing is not an exclusive scheme for representing negative integers, rather we can say that the binary representation of integers are always the same, we just negate the weight of the most significant bit. And that bit determines the sign of the integer.
In C, there is a keyword unsigned (not available in java), which can be used for declaring unsigned int x;. In the unsigned integers, the weight of the MSB is positive (2^31) rather than being negative. In that case the range of an unsigned int is 0 to 2^32 - 1, while an int has range -2^31 to 2^31 - 1.
From another point of view, if you consider the two's complement of x as ~x + 1 (NOT x plus one), here's the explanation:
For any x, ~x is just the bitwise inverse of x, so wherever x has a 1-bit, ~x will have a 0-bit there (and vice versa). So, if you add these up, there will be no carry in the addition and the sum will be just an integer every bit of which is 1.
For 32-bit integers:
x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 = 1111 1111 1111 1111 1111 1111 1111 1111 + 1
= 1 0000 0000 0000 0000 0000 0000 0000 0000
The leftmost 1-bit will simply be discarded, because it doesn't fit in 32-bits (integer overflow). So,
x + ~x + 1 = 0
-x = ~x + 1
So you can see that the negative x can be represented by ~x + 1, which we call the two's complement of x.
I have ran the following program to know it
public class Negative {
public static void main(String[] args) {
int i =10;
int j = -10;
System.out.println(Integer.toBinaryString(i));
System.out.println(Integer.toBinaryString(j));
}
}
Output is
1010
11111111111111111111111111110110
From the output it seems that it has been using two's complement.
Oracle provides some documentation regarding Java Datatypes that you may find interesting. Specifically:
int: The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).
Btw, short is also stored as two's complement.
Positive numbers are stored/retrived as it is.
e.g) For +ve number 10; byte representation will be like 0-000 0010
(0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve,
so the value will be taken as it is.
But negative numbers will be stored after 2's complement (other than
MSB bit), and MSB bit will be set to 1.
e.g) when storing -10 then
0-000 0010 -> (1's complement) -> 0-111 1101
-> (2's complement) 0-111 1101 + 1 -> 0-111 1110
Now MSB will be set to one, since it is negative no -> 1-111 1110
when retrieving, it found that MSB is set to 1. So it is negative no.
And 2's complement will be performed other than MSB.
1-111 1110 --> 1-000 0001 + 1 --> 1-000 0010
Since MSB representing this is negative 10 --> hence -10 will be retrived.
Casting
Also note that when you are casting int/short to byte, only last byte will be considered along with last byte MSB,
Take example "-130" short, it might be stored like below
(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110
Now byte casting took last byte which is 0111 1110. (0-MSB)
Since MSB says it is +ve value, so it will be taken as it is.
Which is 126. (+ve).
Take another example "130" short, it might be stored like below
0-000 000 1000 0010 (MSB = 0)
Now byte casting took last byte which is 1000 0010 . (1=MSB)
Since MSB says it is -ve value, 2's complement will be performed and negative number will be returned. So in this case -126 will be returned.
1-000 0010 -> (1's complement) -> 1-111 1101
-> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
= -126
Diff between (int)(char)(byte) -1 AND (int)(short)(byte) -1
(byte)-1 -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111 (sign bit is carry forwarded on left)
similarly
(short)(byte)-1-> 1-111 1111 1111 1111 (sign bit is carry forwarded on left)
But
(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111 = 65535
since char is unsigned; MSB won't be carry forwarded.
AND
(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded.
References
Why is two's complement used to represent negative numbers?
What is “2's Complement”?
The most significant bit (32nd) indicates that the number is positive or negative. If it is 0, it means the number is positive and it is stored in its actual binary representation. but if it is 1, it means the number is negative and is stored in its two's complement representation. So when we give weight -2^32 to the 32nd bit while restoring the integer value from its binary representation, We get the actual answer.
According to this document, all integers are signed and stored in two's complement format for java. Not certain of its reliability..
positive numbers are stored directly as binary. 2's compliment is required for negative numbers.
for example:
15 : 00000000 00000000 00000000 00001111
-15: 11111111 11111111 11111111 11110001
here is the difference in signed bit.
Thank you, dreamcrash for the answer https://stackoverflow.com/a/13422442/1065835; on the wiki page they give an example which helped me understand how to find out the binary representation of the negative counterpart of a positive number.
For example, using 1 byte (= 2 nibbles = 8 bits), the decimal number 5
is represented by
0000 01012 The most significant bit is 0, so the pattern represents a
non-negative value. To convert to −5 in two's-complement notation, the
bits are inverted; 0 becomes 1, and 1 becomes 0:
1111 1010 At this point, the numeral is the ones' complement of the
decimal value −5. To obtain the two's complement, 1 is added to the
result, giving:
1111 1011 The result is a signed binary number representing the
decimal value −5 in two's-complement form. The most significant bit is
1, so the value represented is negative.
For positive integer 2'complement value is same with MSB bit 0 (like +14 2'complement is 01110).
For only negative integer only we are calculating 2'complement value (-14= 10001+1 = 10010).
So final answer is both the values(+ve and -ve) are stored in 2'complement form only.
This method BigInteger.bitCount() "Returns the number of bits in the two's complement representation of this BigInteger that differ from its sign bit."
If the number is positive, it is the count of 1 bits in the number.
I have difficulty to get the negative number right.
For example, number -1377605392 's binary representation is -1010010000111001001011100010000. It has 12 1s and 19 0s.
But java code BigInteger.valueOf((long)-1377605392) give result of 15!!
How does this 15 is calculated?
The two's complement representation of a binary number means:
subtract 1
switch all 1 to 0 and 0 to 1
Compare the two's complement of -1377605392 with the corresponding positive number:
1111111111111111111111111111111110101101111000110110100011110000
0000000000000000000000000000000001010010000111001001011100010000
As you can see, all bits are flipped, except the trailing zeroes.
However, in BigInteger, negative numbers are stored as the absolute (that is: positive) value with a separate sign-bit, so to count the number of 0 in a negative number, the pasted code counts the number of 1 in the absolute value, adds the number of trailing zeroes (which are still 0) and subtracts 1 (for the last 1 which is still there)
The reason for using two's complement is that it makes basic arithmetics really simple, and the logic can ignore the sign. For example (using 8-bit numbers for simplicity):
6 = 00000110
-2 = 11111110
4 = 00000100 (adding together with carry)
You should do som excercises on paper with smaller numbers to understand how this works.
In java when I say Integer i = Math.abs(Integer.MIN_VALUE). I get the same value as the answer,which means i contains Integer.MIN_VALUE.
I have verified the same in C++ as well.
Why this behavior?
Read this in Effective Java by Joshua Bloch.
I found the answer for this question and here is the explanation:
Computers work with binary arithmentic, the logic of Math.abs in java or the absolute function in any language is like below:
if(num >= 0)
return num;
else
return (2's complement of the num);
Note : How to find 2's complement
For a given number, we find it's 1's complement first and then add 1 to it. For e.g.
Consider our number to be 10101
1's complement= 01010
2's complement= 01011 (added 1 to the 1`s complement)
Now, for the sake of making it easy and clear, let us say that our Integer(signed) size is 3 bit, then here is the possible list of numbers which can be produced using the four bits:
000 --> 0 (0)
001 --> 1 (1)
010 --> 2 (2)
011 --> 3 (3)
100 --> 4 (-4)
101 --> 5 (-3)
110 --> 6 (-2)
111 --> 7 (-1)
Now that this is signed, it means half of the numbers are negative and the other half are positive(The negative numbers are the ones with the first bit 1). Let us start from 000 and try to find its negative number, it would be the two's complement of 000.
2's complement of `000` = 1 + `111` = `000`
2's complement of `001` = 1 + `110` = `111`
2's complement of `010` = 1 + `101` = `110`
2's complement of `011` = 1 + `100` = `101`
2's complement of `100` = 1 + `011` = `100`
2's complement of `101` = 1 + `010` = `011`
2's complement of `110` = 1 + `001` = `010`
2's complement of `111` = 1 + `000` = `001`
From the above demonstration, we find that 2's complement of 111(-1) is 001(1), similarly 2's complement of 110(-2) is 010(2), 2's complement of 101(-3) is 011(3) and 2's complement of 100(-4) is 100(-4) and as we can see that -4 is the smallest negative number possible using 3 bits.
This is the reason why absolute of Integer.MIN_VALUE is Integer.MIN_VALUE.
There is an inherent asymmetry that is the root cause of this effect. The number of 32-bit bit patterns is even. One of those patterns is used for zero. That leaves an odd number of non-zero values. The number of positive values and the number of negative values cannot be equal because their sum is odd.
In the 2's complement representation used for Java integers, the number of negative numbers is one greater than the number of positive numbers. Each negative number other than Integer.MIN_VALUE corresponds to a positive number that is both its negation and its absolute value. Integer.MIN_VALUE is left over, with no corresponding positive int. Math.abs and negation map it to itself.
Why this behavior?
It is a mathematical consequence of the choice of representation used in all modern computers.
Here's an informal proof of why it has to be that way.
A signed binary number representation with N bits has 2N possible values; i.e. a set integers with an even number of elements.
Remove zero from the set. The set is now has an odd number of elements.
Now remove all pairs of numbers of the form {n, -n}. Each time we remove a pair of numbers, the set still contains an odd number of elements.
We are now left with a set that contains an odd number of integers for which n is in the set, but -n is not in the set. Since the set size is odd, it cannot be empty; i.e. there is at least one number with this property.
In the representations specified by Java (and indeed used all other practical languages), integer types have 2N-1 negative values and 2N-1 - 1 values greater than zero. The value that has the strange property is MIN_VALUE. This representation is called two's complement.
Strictly speaking, an integer representation doesn't have to have this anomaly:
It is possible to have two zeros (-0 and +0); e.g. signed magnitude or one's complement representations. (This invalidates step 2 of the proof: there are now 2 zeros to remove.)
It is possible to exclude -2N-1; i.e. make it an illegal value. (This invalidates step 1 of the proof: the initial set now has an odd number of values.)
It is possible to specify integer arithmetic so that (for example) negating MIN_VALUE raises an exception. For instance Math.abs(Integer.MIN_VALUE) would throw an exception.
However, all of these things have significant performance implications, especially since modern computer hardware only supports twos-complement arithmetic natively. They also have issues in relation to writing reliable integer codes ...
Math.abs(int) docs says If the argument is negative, the negation of the argument is returned. JLS 15.15.4. Unary Minus Operator says For all integer values x, -x equals (~x)+1.
-Integer.MIN_VALUE = ~Integer.MIN_VALUE + 1 = ~0x80000000 + 1 = 0x7FFFFFFF + 1 = 0x80000000 = Integer.MIN_VALUE
You might expect that absolute value of Integer.MIN_VALUE would be Integer.MAX_VALUE + 1, but this value is out of primitive int size. And Integer.MAX_VALUE + 1 is Integer.MIN_VALUE again. That's all.
This is because of the way two's-complement number systems work. Integer.MIN_VALUE corresponds to 0x80000000. The standard way to negate it is to take its ones' complement (0x7FFFFFFF in this case) and add 1, and in this case it would overflow back to 0x80000000.
According to docs.oracle.com:-
byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
Byte - 8 bits
2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0
128 64 32 16 8 4 2 1)
Adding all these numbers we get a total of 255. Then how's the range which is -128 to 127 calculated. Is it hard-coded somewhere or there's some more technicality to this range?
Any suggestions would be appreciated.
Let's calculate range for 1 Byte
1 bit can take 0 or 1
1 Byte = 8 Bits
The first bit is used as a sign ( - or + )
then remaining bits are 7
so we can write 2^7 = 128 different numbers for one sign
we get 0 as a positive sign. then we have 128 numbers for the negative side,127 numbers for the positive side and 0 (zero)
so the range is -128 to 127 including 0
It is a signed type, meaning, it still has a range of 255 (as you have correctly calculated), but it starts at -128. So half the range is below zero, 1 possible number is = (zero) and the remaining 127 are above 0.
The first bit is the sign. (1 - minus, 0 - plus)
Formula for Range calculation is : -2^(n-1) to (2^(n-1)-1)
where n = no. of bits of primitive datatype.
Example:
For int datatype, n is 32, in short datatype, n is 16 etc.
So, int range will be: -2^(32-1) to (2^(32-1)-1)
By using the same formula Range of byte, short, float and double could be calculated.
That's because the first bit is used for the sign, since the data type is signed.
Please refer to http://en.wikipedia.org/wiki/Signed_number_representations
Since there is no unsigned primitive types in Java (like C or C#), is usual to cast it to a bigger type if you need to "overflow" the boundaries.
The last bit i.e. number 8 we are writing it 2^7 is a sign bit that decides negative or positive sign so it is 2^0 +2^1 +2^2 +2^3 +2^4 +2^5+ 2^6
Formula to calculate range in Java
-2(n-1) to +2(n-1)-1
Where n is the number of bit (1 byte= 8 bit)
So, for byte type range would be:
-2(8-1) to +2(8-1)-1
or, -2(7) to +2(7)-1
or, -128 to +127
it results from the standard representation of signed values as binary numbers. For a full description see http://en.wikipedia.org/wiki/Two%27s_complement.
-Rich
Let's calculate range for 1 Byte in C Langauge Datatype char
In case of char dataype lets consider -
1 Byte = 8 Bits
2^8 = 256
so we can write 2^8 = 256
In case of unsigned 0 to positive integers only.
4.1 In case of signed
we have 128 numbers for the negative side, 0 (zero) and 127 numbers for the positive side
so the range is -128 0 +127
Here 0 is taking one bit
Bit consists of 0’s and 1’s.byte normally consists of 8 bits.so the values can be calculated using the general formula which is given below,
no of values data type can have=2^n(2 power n), where n represents no of bits.
so the value of byte data type=2^8(i.e 1 byte=8 bits),here n=8
byte value=256
And it should be shared equal on both sides of zero ( half values at negative and half value at positive ). Hence the range for byte is from -128 to 127.
Range of data types
so now we came to know that how we are calculating the Range of the integer data types.This logic is applicable for all the integer data types.
The full details of all the data types are given below,
S.NO Data Type Bits Ranges values
1 boolean 1 – true or false(1 or 0)
2 byte 8 -128 to 127. 256(2^8)
3 short 16 -32,768 to 32,767 65,536(2^16)
4 int 32 -2^31 to (2^31)-1 2^32
5 long 64 Refer NOTE 2^64
6 float 32 Refer NOTE ———
7 double 64 Refer NOTE ———-
8 char 16 0 to 65,535 65,536(2^16)
I am trying to understand how Java stores integer internally. I know all java primitive integers are signed, (except short?). That means one less bit available in a byte for the number.
My question is, are all integers (positive and negative) stored as two's complement or are only negative numbers in two's complement?
I see that the specs says x bit two's complement number. But I often get confused.
For instance:
int x = 15; // Stored as binary as is? 00000000 00000000 00000000 00001111?
int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010
Edit
To be clear, x = 15
In binary as is: `00000000 00000000 00000000 00001111'
Two's complement: `11111111 11111111 11111111 11110001`
So if your answer is all numbers are stored as two's complement then:
int x = 15; // 11111111 11111111 11111111 11110001
int y = -22 // 11111111 11111111 11111111 11101010
The confusion here again is the sign says, both are negative numbers. May be I am misreading / misunderstanding it?
Edit
Not sure my question is confusing. Forced to isolate the question:
My question precisely: Are positive numbers stored in binary as is while negative numbers are stored as two's complement?
Some said all are stored in two's complement and one answer says only negative numbers are stored as two's complement.
Let's start by summarizing Java primitive data types:
byte: Byte data type is an 8-bit signed two's complement integer.
Short: Short data type is a 16-bit signed two's complement integer.
int: Int data type is a 32-bit signed two's complement integer.
long: Long data type is a 64-bit signed two's complement integer.
float: Float data type is a single-precision 32-bit IEEE 754 floating point.
double: double data type is a double-precision 64-bit IEEE 754 floating point.
boolean: boolean data type represents one bit of information.
char: char data type is a single 16-bit Unicode character.
Source
Two's complement
"The good example is from wiki that the relationship to two's complement is realized by noting that 256 = 255 + 1, and (255 − x) is the ones' complement of x
0000 0111=7 two's complement is 1111 1001= -7
the way it works is the MSB(the most significant bit) receives a negative value so in the case above
-7 = 1001= -8 + 0+ 0+ 1
Positive integers are generally stored as simple binary numbers (1 is 1, 10 is 2, 11 is 3, and so on).
Negative integers are stored as the two's complement of their absolute value. The two's complement of a positive number is when using this notation a negative number.
Source
Since I received a few points for this answer, I decided to add more information to it.
A more detailed answer:
Among others there are four main approaches to represent positive and negative numbers in binary, namely:
Signed Magnitude
One's Complement
Two's Complement
Bias
1. Signed Magnitude
Uses the most significant bit to represent the sign, the remaining bits are used to represent the absolute value. Where 0 represents a positive number and 1 represents a negative number, example:
1011 = -3
0011 = +3
This representation is simpler. However, you cannot add binary numbers in the same way that you add decimal numbers, making it harder to be implemented at the hardware level. Moreover, this approach uses two binary patterns to represent the 0, -0 (1000) and +0 (0000).
2. One's Complement
In this representation, we invert all the bits of a given number to find out its complementary. For example:
010 = 2, so -2 = 101 (inverting all bits).
The problem with this representation is that there still exist two bits patterns to represent the 0, negative 0 (1111) and positive 0 (0000)
3. Two's Complement
To find the negative of a number, in this representation, we invert all the bits and then add one bit. Adding one bit solves the problem of having two bits patterns representing 0. In this representation, we only have one pattern for
0 (0000).
For example, we want to find the binary negative representation of 4 (decimal) using 4 bits. First, we convert 4 to binary:
4 = 0100
then we invert all the bits
0100 -> 1011
finally, we add one bit
1011 + 1 = 1100.
So 1100 is equivalent to -4 in decimal if we are using a Two's Complement binary representation with 4 bits.
A faster way to find the complementary is by fixing the first bit that as value 1 and inverting the remaining bits. In the above example it would be something like:
0100 -> 1100
^^
||-(fixing this value)
|--(inverting this one)
Two's Complement representation, besides having only one representation for 0, it also adds two binary values in the same way that in decimal, even numbers with different signs. Nevertheless, it is necessary to check for overflow cases.
4. Bias
This representation is used to represent the exponent in the IEEE 754 norm for floating points. It has the advantage that the binary value with all bits to zero represents the smallest value. And the binary value with all bits to 1 represents the biggest value. As the name indicates, the value is encoded (positive or negative) in binary with n bits with a bias (normally 2^(n-1) or 2^(n-1)-1).
So if we are using 8 bits, the value 1 in decimal is represented in binary using a bias of 2^(n-1), by the value:
+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
Java integers are of 32 bits, and always signed. This means, the most significant bit (MSB) works as the sign bit. The integer represented by an int is nothing but the weighted sum of the bits. The weights are assigned as follows:
Bit# Weight
31 -2^31
30 2^30
29 2^29
... ...
2 2^2
1 2^1
0 2^0
Note that the weight of the MSB is negative (the largest possible negative actually), so when this bit is on, the whole number (the weighted sum) becomes negative.
Let's simulate it with 4-bit numbers:
Binary Weighted sum Integer value
0000 0 + 0 + 0 + 0 0
0001 0 + 0 + 0 + 2^0 1
0010 0 + 0 + 2^1 + 0 2
0011 0 + 0 + 2^1 + 2^0 3
0100 0 + 2^2 + 0 + 0 4
0101 0 + 2^2 + 0 + 2^0 5
0110 0 + 2^2 + 2^1 + 0 6
0111 0 + 2^2 + 2^1 + 2^0 7 -> the most positive value
1000 -2^3 + 0 + 0 + 0 -8 -> the most negative value
1001 -2^3 + 0 + 0 + 2^0 -7
1010 -2^3 + 0 + 2^1 + 0 -6
1011 -2^3 + 0 + 2^1 + 2^0 -5
1100 -2^3 + 2^2 + 0 + 0 -4
1101 -2^3 + 2^2 + 0 + 2^0 -3
1110 -2^3 + 2^2 + 2^1 + 0 -2
1111 -2^3 + 2^2 + 2^1 + 2^0 -1
So, the two's complement thing is not an exclusive scheme for representing negative integers, rather we can say that the binary representation of integers are always the same, we just negate the weight of the most significant bit. And that bit determines the sign of the integer.
In C, there is a keyword unsigned (not available in java), which can be used for declaring unsigned int x;. In the unsigned integers, the weight of the MSB is positive (2^31) rather than being negative. In that case the range of an unsigned int is 0 to 2^32 - 1, while an int has range -2^31 to 2^31 - 1.
From another point of view, if you consider the two's complement of x as ~x + 1 (NOT x plus one), here's the explanation:
For any x, ~x is just the bitwise inverse of x, so wherever x has a 1-bit, ~x will have a 0-bit there (and vice versa). So, if you add these up, there will be no carry in the addition and the sum will be just an integer every bit of which is 1.
For 32-bit integers:
x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 = 1111 1111 1111 1111 1111 1111 1111 1111 + 1
= 1 0000 0000 0000 0000 0000 0000 0000 0000
The leftmost 1-bit will simply be discarded, because it doesn't fit in 32-bits (integer overflow). So,
x + ~x + 1 = 0
-x = ~x + 1
So you can see that the negative x can be represented by ~x + 1, which we call the two's complement of x.
I have ran the following program to know it
public class Negative {
public static void main(String[] args) {
int i =10;
int j = -10;
System.out.println(Integer.toBinaryString(i));
System.out.println(Integer.toBinaryString(j));
}
}
Output is
1010
11111111111111111111111111110110
From the output it seems that it has been using two's complement.
Oracle provides some documentation regarding Java Datatypes that you may find interesting. Specifically:
int: The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).
Btw, short is also stored as two's complement.
Positive numbers are stored/retrived as it is.
e.g) For +ve number 10; byte representation will be like 0-000 0010
(0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve,
so the value will be taken as it is.
But negative numbers will be stored after 2's complement (other than
MSB bit), and MSB bit will be set to 1.
e.g) when storing -10 then
0-000 0010 -> (1's complement) -> 0-111 1101
-> (2's complement) 0-111 1101 + 1 -> 0-111 1110
Now MSB will be set to one, since it is negative no -> 1-111 1110
when retrieving, it found that MSB is set to 1. So it is negative no.
And 2's complement will be performed other than MSB.
1-111 1110 --> 1-000 0001 + 1 --> 1-000 0010
Since MSB representing this is negative 10 --> hence -10 will be retrived.
Casting
Also note that when you are casting int/short to byte, only last byte will be considered along with last byte MSB,
Take example "-130" short, it might be stored like below
(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110
Now byte casting took last byte which is 0111 1110. (0-MSB)
Since MSB says it is +ve value, so it will be taken as it is.
Which is 126. (+ve).
Take another example "130" short, it might be stored like below
0-000 000 1000 0010 (MSB = 0)
Now byte casting took last byte which is 1000 0010 . (1=MSB)
Since MSB says it is -ve value, 2's complement will be performed and negative number will be returned. So in this case -126 will be returned.
1-000 0010 -> (1's complement) -> 1-111 1101
-> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
= -126
Diff between (int)(char)(byte) -1 AND (int)(short)(byte) -1
(byte)-1 -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111 (sign bit is carry forwarded on left)
similarly
(short)(byte)-1-> 1-111 1111 1111 1111 (sign bit is carry forwarded on left)
But
(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111 = 65535
since char is unsigned; MSB won't be carry forwarded.
AND
(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded.
References
Why is two's complement used to represent negative numbers?
What is “2's Complement”?
The most significant bit (32nd) indicates that the number is positive or negative. If it is 0, it means the number is positive and it is stored in its actual binary representation. but if it is 1, it means the number is negative and is stored in its two's complement representation. So when we give weight -2^32 to the 32nd bit while restoring the integer value from its binary representation, We get the actual answer.
According to this document, all integers are signed and stored in two's complement format for java. Not certain of its reliability..
positive numbers are stored directly as binary. 2's compliment is required for negative numbers.
for example:
15 : 00000000 00000000 00000000 00001111
-15: 11111111 11111111 11111111 11110001
here is the difference in signed bit.
Thank you, dreamcrash for the answer https://stackoverflow.com/a/13422442/1065835; on the wiki page they give an example which helped me understand how to find out the binary representation of the negative counterpart of a positive number.
For example, using 1 byte (= 2 nibbles = 8 bits), the decimal number 5
is represented by
0000 01012 The most significant bit is 0, so the pattern represents a
non-negative value. To convert to −5 in two's-complement notation, the
bits are inverted; 0 becomes 1, and 1 becomes 0:
1111 1010 At this point, the numeral is the ones' complement of the
decimal value −5. To obtain the two's complement, 1 is added to the
result, giving:
1111 1011 The result is a signed binary number representing the
decimal value −5 in two's-complement form. The most significant bit is
1, so the value represented is negative.
For positive integer 2'complement value is same with MSB bit 0 (like +14 2'complement is 01110).
For only negative integer only we are calculating 2'complement value (-14= 10001+1 = 10010).
So final answer is both the values(+ve and -ve) are stored in 2'complement form only.