HashMap源码学习序章之计算机基础篇

439 阅读8分钟

前言

​ 由于HashMap内部机制较为复杂,本章先介绍一些基础逻辑以及基本概念,为下章的源码分析做铺垫。

本文内容

  1. 机器数,真值,原码, 反码, 补码
  2. 各个进制之间的相互计算
  3. 位运算符

一、机器数和真值

​ 首先要介绍机器数和真值的概念

Int类型的变量占4字节(byte),32位(32bit),这里缩减了32位的长度为16位,方便阅读

1.机器数

  • 数字在计算机之中的表示即为机器数,机器数的最高位为符号位,正数为1,负数为0。

    例子如下:

10进制值机器数
100000 0000 0000 1010
-101000 0000 0000 1010

2.真值

  • 因为机器数的最高位为符号位,不能等于真正的数值,所以真值的最高位为符号位,正数为+,负数为-

    例子如下:

10进制值机器数真值
100000 0000 0000 1010+000 0000 0000 1010
-101000 0000 0000 1010-000 0000 0000 1010

二、原码,反码,补码

​ 计算机要使用一定的编码方式进行存储,原码反码, 补码,是机器存储一个具体数字的编码方式。

1.原码

  • 原码的最高位为符号位,正数为1,负数为0。加上真值的绝对值。所以8位的二进制数的取值范围是,[1111 1111 1111 1111 , 0111 1111 1111 1111],即[-32767, 32767]

    例子如下:

10进制值原码真值
100000 0000 0000 1010+000 0000 0000 1010
-101000 0000 0000 1010-000 0000 0000 1010

2.反码

​ 反码规则如下:

  • 正数的反码是原码本身

  • 负数的反码符号位不变,其余各位取反

    例子如下:

10进制值原码反码
100000 0000 0000 10100000 0000 0000 1010
-101000 0000 0000 10101111 1111 1111 0101

3.补码

​ 补码规则如下:

  • 正数的补码是反码本身

  • 负数的补码是反码的基础上+1

    例子如下:

10进制值原码反码补码
100000 0000 0000 10100000 0000 0000 10100000 0000 0000 1010
-101000 0000 0000 10101111 1111 1111 01011111 1111 1111 0110

4.原码,反码,补码为何存在

  • 如果要计算机通过辨别符号位会使基础电路设计变得十分复杂,所以运用数学原理,减去一个正数相当于加上一个负数,所以计算机只通过加法就可实现加减。如果用原码进行计算显然是错的,我们如果用反码计算会得到如下结果。

    ​ 十进制计算:10+10=20

    ​ 二进制反码计算:0000 0000 0000 1010 + 1111 1111 1111 0101 = 1111 1111 1111 1111

    ​ 1111 1111 1111 1111 的原码为 1000 0000 0000 0000 = -0

    虽然通过反码计算,结果的真值是正确的,但是0带符号位是没有意义的,我们在尝试用补码计算,会得到如下结果。

    ​ 十进制计算:10+10=20

    ​ 二进制补码计算:0000 0000 0000 1010 + 1111 1111 1111 0110 = 0000 0000 0000 0000

    ​ 0000 0000 0000 0000 的原码为 0000 0000 0000 0000 = 0

    这样就可以解决-0的问题,并且1000 0000 0000 0000表示-32768。另外-1-32767=-32768,在补码运算中为1000 0000 0000 0000就是-32768, 但是注意因为实际上是使用以前的-0的补码来表示-32768, 所以-32768并没有原码和反码表示.(对-32768的补码表示1000 0000 0000 0000算出来的原码是0000 0000 000 0000, 这是不正确的)


三、进制计算

1.二进制 → 十进制

二进制数从低位到高位(即从右往左)计算,第0位的权值是2的0次方,第1位的权值是2的1次方,第2位的权值是2的2次方,依次递增下去,把最后的结果相加的值就是十进制的值了。

  例:将二进制的(101011)转换为十进制的步骤如下:

​ 第0位 1 x 2^0 = 1

​ 第1位 1 x 2^1 = 2

       第2位 0 x 2^2 = 0

​ 第3位 1 x 2^3 = 8

​ 第4位 0 x 2^4 = 0

​ 第5位 1 x 2^5 = 32

​ 1+2+0+8+0+32=43,即(101011)=(43)


2.十进制→ 二进制

除2取余法,即每次将整数部分除以2,余数为该位权上的数,而商继续除以2,余数又为上一个位权上的数,这个步骤一直持续下去,直到商为0为止,最后读数时候,从最后一个余数读起,一直到最前面的一个余数。

​ 例:将十进制的(43)转换为二进制的步骤如下:

​ 将商43除以2,商21余数为1

​ 将商21除以2,商10余数为1

​ 将商10除以2,商5余数为0

​ 将商5除以2,商2余数为1

​ 将商2除以2,商1余数为0

​ 将商1除以2,商0余数为1

​ 因为最后一位是经过多次除以2才得到的,因此它是最高位,读数字从最后的余数向前读,101011,即(43)=(101011)


3.扩展

1.包含小数的进制换算

​ (ABC.8C)H=10x16^2+11x16^1+12x16^0+8x16^-1+12x16^-2

​ =2560+176+12+0.5+0.046875

​ =(2748.546875)D


2. 负次幂的计算:

​ 2^-5=2^(0-5)=2^0/2^5=1/2^5

​ 同底数幂相除,底数不变,指数相减,反过来


四、位运算符

1.<<左移

​ 低位补0,高位被遗弃

  • 正数:r = 20 << 2

  20的二进制补码:0001 0100

  向左移动两位后:0101 0000

       结果:r = 80

  • 负数:r = -20 << 2

  -20 的二进制原码 :1001 0100

  -20 的二进制反码 :1110 1011

  -20 的二进制补码 :1110 1100

  左移两位后的补码:1011 0000

        反码:1010 1111

        原码:1101 0000

        结果:r = -80


2.>>右移

​ 该数为正,则高位补0,若为负数,则高位补1,低位被遗弃

  • 正数:r = 20 >> 2

  20的二进制补码:0001 0100

  向右移动两位后:0000 0101

       结果:r = 5

  • 负数:r = -20 >> 2

  -20 的二进制原码 :1001 0100

  -20 的二进制反码 :1110 1011

  -20 的二进制补码 :1110 1100

  右移两位后的补码:1111 1011

        反码:1111 1010

        原码:1000 0101

        结果:r = -5


3.>>>逻辑右移(无符号右移)

​ 高位补0(无视正负),低位被遗弃

  • 正数: r = 20 >>> 2

    的结果与 r = 20 >> 2 相同;

  • 负数: r = -20 >>> 2

    注:以下数据类型默认为Int32位

  -20:源码:1000 0000 0000 0000 0000 0000 0001 0100

    反码:1111 1111 1111 1111 1111 1111 1110 1011

    补码:1111 1111 1111 1111 1111 1111 1110 1100

    右移:0011 1111 1111 1111 1111 1111 1111 1011

    结果:r = 1073741819


当Int类型的数据进行左移的时候,当左移的位数大于等于32位的时候,位数会先求余数,然后再进行左移,右移同理

4.&(与操作符)

同为1结果为1,否则为0

  • 0 & 0 = 0
  • 0 & 1 = 0
  • 1 & 0 = 0
  • 1 & 1 =1

5.|(或操作方)

1出现为1,否则为0

  • 0 | 0 = 0
  • 0 | 1 = 1
  • 1 | 0 = 1
  • 1 | 1 = 1

6.^(异或操作符)

不同为1,相同为0

  • 0 ^ 0 = 0
  • 0 ^ 1 = 1
  • 1 ^ 0 = 1
  • 1 ^ 1 = 0

7.~(取反操作符)

​ 0变1,1变0

总结

本文讲述的都是计算机基础,为了下章的扰乱函数解析做出铺垫,也可当作字典,当知识遗忘时可供查阅。