(byte)1658385462>>16=-40, how to calculate?

text

mongo-java-driverThere is a class in the Github project ObjectId.java, its function is to generate a unique id, and its core implementation is the following piece of code [1]:

public void putToByteBuffer(final ByteBuffer buffer) {
    
    
    notNull("buffer", buffer);
    isTrueArgument("buffer.remaining() >=12", buffer.remaining() >= OBJECT_ID_LENGTH);

    buffer.put(int3(timestamp));
    buffer.put(int2(timestamp));
    buffer.put(int1(timestamp));
    buffer.put(int0(timestamp));
    buffer.put(int2(randomValue1));
    buffer.put(int1(randomValue1));
    buffer.put(int0(randomValue1));
    buffer.put(short1(randomValue2));
    buffer.put(short0(randomValue2));
    buffer.put(int2(counter));
    buffer.put(int1(counter));
    buffer.put(int0(counter));
}

The methods in the above code int2()are defined as follows:

private static byte int2(int x) {
    
    
    return (byte) (x >> 16);
}

Take the current timestamp (seconds) 1658385462, let's test this method:

@Test
public void test() {
    
    
    System.out.println(int2(1658385462)); // -40
}

The result obtained is -40. Namely: (byte) 1658385462 >> 16 = -40.

How is this calculated?

calculation process

1. First, the computer needs to convert 1658385462 into a binary number.

Because int is 4 bytes and 32 bits, the corresponding binary result is as follows:

0110 0010 1101 1000 1111 0100 0011 0110

2. Execute >>16 operation.

The operation result is 0110 0010 1101 1000.

0110 0010 1101 1000 1111 0100 0011 0110 >> 16 = 0110 0010 1101 1000

3. Because the computer stores the filling, it needs to be converted into filling.

The complement of a positive number is itself, and the complement is: 0110 0010 1101 1000.

4. Because byte is 1 byte with 8 bits, the computer only reserves the last 8 bits during forced conversion.

The result of reserving 8 bits is: 1101 1000.

5. The value after 8 digits is reserved is still filled, and it needs to be converted to the original position to be displayed to the user.

补:1101 1000
反:1101 0111
原:1010 1000

6. The highest bit 1 means a negative number, convert 010 1000 into a decimal number, then it is -40.

What are original code, inverse code and complement code?

Original code: The original code is the absolute value of the sign bit plus the true value, that is, the first bit is used to represent the symbol, and the remaining bits are used to represent the value.

One's complement: The one's complement of a positive number is itself. The one's complement of a negative number is based on the original code, the sign bit remains unchanged, and the rest of the bits are reversed.

Complement: The complement of a positive number is itself. The complement code of negative numbers is based on the original code, the sign bit remains unchanged, and the rest of the bits are reversed, and finally +1.

It is not difficult to see from the original code, inverse code, and complement code that the original code is the most intuitive way to see the value, so why do we need inverse code and complement code?

The answer is to simplify the design of computer integrated circuits.

Our human brain can distinguish that the first bit is the sign bit. When calculating, we will choose the addition and subtraction of the true value area according to the sign bit. But for computers, identifying the "sign bit" will obviously make the basic circuit design of the computer very complicated, so people came up with a method to include the sign bit in the calculation.

We know that according to the algorithm: subtracting a positive number is equal to adding a negative number, that is: 1-1 = 1 + (-1) = 0, so the machine can only add but not subtract, so that the design of computer operations is simpler up. In addition, since computer CPUs are good at addition operations at this stage, CPU hardware implementation of subtraction is much more complicated, and the operation efficiency is very low, so we are lazy and only discuss addition operations. Maybe in the future, subtraction acceleration hardware will be invented, so that's another matter.

Why is there a reverse code?

So people began to explore the method of using the sign bit to participate in the operation and only retaining the addition. First look at the original code: calculate the decimal expression: 1-1=0.

1 - 1
= 1 + (-1) = [00000001]原 + [10000001]原
= [10000010]原
= -2

If it is represented by the original code and the sign bit is also involved in the calculation, it is obvious that the result is incorrect for subtraction. This is why the computer does not use the original code to represent a number.

In order to solve the problem of subtracting the original code, an inverse code appeared.

1 - 1
= 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [0000 0001]反 + [1111 1110]反
= [1111 1111]反
= [1000 0000]原
= -0

It is found that the truth value part of the result is correct when the subtraction is calculated by one's complement.

Why is there a complement?

Computing the subtraction with one's complement, the truth part of the result is correct. The only problem is actually the special value "0". While people understand +0 and -0 to be the same, 0 being signed doesn't make any sense. And there will be [0000 0000]原and [1000 0000]原two codes representing 0.

So the complement code appeared, in order to solve the two encoding problems of the sign of 0 and 0:

1 - 1
= 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [0000 0001]补 + [1111 1111]补
= [0000 0000]补
= [0000 0000]原

In this way, 0 is represented by [0000 0000], and -0, which had problems before, does not exist. Is the other encoding [1000 0000] deprecated?

(-1) + (-127)
= [1000 0001]原 + [1111 1111]原
= [1111 1111]补 + [1000 0001]补
= [1000 0000]补

The result of -1-127 should be -128, just [1000 0000] can be used to represent -128. In the result of the two's complement operation, [1000 0000]补it is -128.

But note: -128 does not have the original code and inverse code representation. [1000 0000]补The original code calculated by the complement of -128 is [0000 0000]原, which is obviously incorrect.

Using two's complement not only fixes the sign of 0 and the problem of two encodings, but also expresses one more lowest number. So in the end it is also 8-bit binary, the range represented by original code or inverse code is [-127, +127], and the range represented by complement code is [-128, 127].

summary

I have sorted out the knowledge digestion link of this article, as follows.

使用原码计算减法的结果是错误的
-> 出现了反码
-> 使用反码计算的 0 有两个,+0 和 -0
-> 出现了补码

For more technical dry goods, please pay attention to the official account "Student Yang technotes", welcome technical exchanges.

Links mentioned in the text

References

Guess you like

Origin blog.csdn.net/yang237061644/article/details/128444716