How does Java calculate negative numbers?

2020-08-14 02:14发布

问题:

I use the ~ operation for bit manipulation, and I'm just wondering how Java calculates the negative number?

I checked the Java documentation:

"The unary bitwise complement operator "~" inverts a bit pattern; it can be applied to any of the integral types, making every "0" a "1" and every "1" a "0". For example, a byte contains 8 bits; applying this operator to a value whose bit pattern is "00000000" would change its pattern to "11111111"."

So if int a = 60 (0011 1100), then int c = ~a (1100 0011).

The question is, how Java calculate negative numbers so that 1100 0011 = -61? The only way 1100 0011 is calculated -61 is

  1. the highest bit is the sign bit.
  2. -2^6 + 2^1 + 2^0 = -61.

But this make no sense to me.

回答1:

The assumption that the highest bit is a simple sign bit is wrong. Java, as well as most modern programming languages (and hardware architectures) use the so-called two's complement representation for numbers. (The bit itself, coincidentally, does indicate the sign, but not in the way you would expect it to, i.e. 150 and -150 have more differences than just the sign bit in their representation.)

This representation might seem like an odd choice at first, but it actually makes operations such as adding a positive number to a negative number (or variations of this) automagically work, without making the processor have to check for special cases.

According to the relevant Wikipedia article:

The system is useful in simplifying the implementation of arithmetic on computer hardware. Adding 0011 (3) to 1111 (−1) at first seems to give the incorrect answer of 10010. However, the hardware can simply ignore the left-most bit to give the correct answer of 0010 (2). Overflow checks still must exist to catch operations such as summing 0100 and 0100. The system therefore allows addition of negative operands without a subtraction circuit and a circuit that detects the sign of a number. Moreover, that addition circuit can also perform subtraction by taking the two's complement of a number (see below), which only requires an additional cycle or its own adder circuit. To perform this, the circuit merely pretends an extra left-most bit of 1 exists.

See this related answer for an even more in-depth explanation with lots of nice, easy to understand examples.



回答2:

Java's primitive numeral data types - int, long, byte, and short are represented in two's complement. What this means:

  • The highest value is the result of all bits set to 1, save for the MSB.
    • Example: 0111 1111 = 127
  • The MSB being set to 1 and all other bits set to 0 is the lowest value.
    • Example: 1000 0000 = -128

The only negative value here is the MSB, so if we break it down into this representation, we'll arrive at -61:

|-128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|  1  |  1 | 0  |  0 | 0 | 0 | 1 | 1 |

-128 + 64 + 2 + 1 = -61.


标签: java bit