Detailed explanation of the complement of the original code and the difference between >> and >>> in java

1. Number of machines and true value

Before learning the original code, inverse code and complement, you need to understand the concept of machine number and truth value.

1. Number of machines

The binary representation of a number in a computer is called the machine number of this number. Machine numbers are signed. The computer uses the most significant bit of a number to store the sign. A positive number is 0 and a negative number is 1.

For example, the number +3 in decimal, the computer word length is 8 bits, and converted to binary is 00000011. If it is -3, it is 10000011.

Then, 00000011 and 10000011 here are the number of machines.

2. Truth

Because the first bit is the sign bit, the formal value of the machine number is not equal to the real value. For example, the above signed number 100000011, its highest bit 1 represents negative, and its real value is -3 instead of the formal value 131 (10000011 converted to decimal is equal to 131). Therefore, for the sake of distinction, the true value corresponding to the signed machine number is called the true value of the machine number.

Example: The true value of 0000 0001 = +000 0001 = +1, the true value of 1000 0001 = –000 0001 = –1

 

2. The basic concepts and calculation methods of original code, inverse code, and complement code.

Before exploring why the machine uses the complement code, let us first understand the concepts of the original code, the complement code and the complement code. For a number, the computer must use a certain encoding method for storage. The original code, the complement code, and the complement code are machine storage The encoding method of a specific number.

1. 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 sign, and the remaining bits are used to represent the value. For example, if it is an 8-bit binary:

[+1] Original  = 0000 0001

[-1] Original  = 1000 0001

The first bit is the sign bit. Because the first bit is the sign bit, the range of 8-bit binary numbers is:

[1111 1111 , 0111 1111]

which is

[-127 , 127]

The original code is the easiest way to understand and calculate the human brain.

2. One's complement

The representation of the inverse code is:

The complement of a positive number is itself

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

[+1] = [00000001] = [00000001]

[-1] = [10000001] = [11111110]

可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.

3. 补码

补码的表示方法是:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[+1] = [00000001] = [00000001] = [00000001]

[-1] = [10000001] = [11111110] = [11111111]

对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.

 

三. 为何要使用原码, 反码和补码

在开始深入学习前, 我的学习建议是先"死记硬背"上面的原码, 反码和补码的表示方式以及计算方法.

现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:

[+1] = [00000001] = [00000001] = [00000001]

所以不需要过多解释. 但是对于负数:

[-1] = [10000001] = [11111110] = [11111111]

可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢?

首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.

于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:

计算十进制的表达式: 1-1=0

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

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

为了解决原码做减法的问题, 出现了反码:

计算十进制的表达式: 1-1=0

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

发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]和[1000 0000]两个编码表示0.

于是补码的出现, 解决了0的符号以及两个编码的问题:

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

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

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

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000] 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000], 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

Java中>> 和 >>>的区别

        到这里,基本知识我们已经了解的很清楚了,那么对于Java 中的移位运算符>> 和 >>>,有什么区别呢?

        无论>>还是>>>都是针对二进制数进行操作的。

        1、右移运算符>>使指定值的所有位都右移规定的次数。右边移出去的部分扔掉不要,左边空出来的部分用原来的数字填充(这就是所谓的带符号右移)

                ——比如说5,右移后为00000010。
                ——假设x=-12,表示为32位int型就是 11111111111111111111111111110100 

                x>>2即带符号右移2位,结果是 11111111111111111111111111111101,化为十进制等于-3

        2、>>>与>>唯一的不同是:>>是带符号的移位,而>>>则是不带符号移位无论原来的最左边是什么数,统统都用0填充。

                —— 比如 byte 类型的-1 为8位 11111111(补码表示法)

                b>>>4就是无符号右移4位,即00001111,这样结果就是15。


Guess you like

Origin blog.csdn.net/qq_36961530/article/details/77456112