javamemorybinarystoretwos-complement

How are integers internally represented at the bit level in Java?


I am trying to understand how Java stores integers 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 that the sign says that both are negative numbers. Maybe 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.


Solution

  • Let's start by summarizing Java's 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 following good example is from Wikipedia showing 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 using this notation to represent 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:

    1. Signed Magnitude
    2. Ones' Complement
    3. Two's Complement
    4. 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. Ones' Complement

    In this representation, we invert all the bits of a given number to find out its complement. 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 bit 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 number is by fixing the first bit that has 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, also allows adding two binary values in the same way as 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 standard for floating points. It has the advantage that the binary value with all bits set to zero represents the smallest value. And the binary value with all bits set 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