第一章 计算机基础知识

1.1 数制及其转换

本章主要讲二进制、十进制、十六进制及其之间互相转换。
可见第二章 数据的表示和运算 > ^xr5xgu

2.1.1 进位计数制及其相互转换

计算机常用整数计数制有二进制、八进制、十进制、十六进制。
这些进制的书写方式为

进制
书写方式
解释
二进制 10101B binary: 二进制
八进制 01234 (C语言中) C语言中以 0 开头表示八进制
十进制 1234D decimalism: 十进制
十六进制 789DAH0x789DA hexadecimal: 十六进制

对于进制计数系统,其有如下的基本概念:

  • 基数:每个数位所用到的不同的符号个数,r进制的基数为r。

2.1.1.1 任意进制转十进制

此外, 进制的进制计数系统的数值计算方式为(主要在于小数点后的计算):
例如:

  • 2进制的
    而该计算方式就是将 进制转化为十进制的计算方式

2.1.1.2 二进制转二的幂进制(二进制与八、十六进制互转)

二进制与八进制互转只需要将三个二进制位分段与对应的八进制位互换即可:

二进制 八进制
000 0
001 1
010 2
011 3
100 4
101 5
110 6
111 7

例如:

  • 二进制 10101.11 -> 补全分段 -> 010 101.110 -> 八进制 25.6
  • 八进制 62.4 -> 二进制 110010.100

十六进制同理,略。

2.1.1.3 十进制转任意进制

十进制转任意进制,整数部分直接用除基取余法即可,例如对于

  1. 计算余数:
    Pasted image 20250225151020.png
  2. 余数从下到上,从左至右排列即可(别忘了最后的0或1也是余数!!!):
    1. 从下到上顺序为:01111011
    2. 则对应二进制为: 1111011B
    小数部分要乘基取整法
  3. 对小数部分乘上基数,然后取走整数部分:
    Pasted image 20250225151519.png
  4. 重复此操作直到最终得到 (如果无法乘出整数则目标进制无法精确表示)
  5. 整数部分从上到下,从左到右排列即可(别忘了最后的1):
    1. 从上到下为:1011
    2. 则小数部分对应二进制为 0.1011B
    最终 123.6875D = 1111011.1011B

2.1.1.4 真值和机器数

基本概念:

  • 真值:符合人类习惯的数字
  • 机器数数字实际在机器中存储的方式涉及浮点数的符号位或整数的负数补码问题等

1.2 计算机中数的表示

计算机中数的表示可以进行如下分类:

  • 定点数:定点数表示法即小数点在数中的位置是固定的,其所固定的位置需要提前约定。可以根据约定的位置不同分为:
    1. 纯整数
      Pasted image 20240331200023.png
    2. 纯小数
      Pasted image 20240331195953.png
    3. 整数+小数
      即约定在中间某位的情况。
      优点:
    4. 运算方便
      缺点:
    5. 要求所有原始数据用比例因子化为小数或整数,运算完还需要化回去。
    6. 需要提前约定小数点位置,不同位置之间的定点数计算能处理的范围小,精度低。
  • 浮点数类似于科学计数法的表示方法,小数点的位置可以移动,且记录于变量内存中

1.2.1 定点数的表示方法

定点数又可以分为:

  • 无符号数( unsigned ):表示范围为
  • 有符号数,根据符号信息表示的方法可以分为:
    • 原码:最高位当符号位。
    • 反码:负数的二进制位表示是对应正数的反码表示。
    • 补码:找一个"无符号正数",使得其加减运算性质和这个"有符号负数"一致。
    • 移码:在补码的基础上,将补码的符号位取反。

1.2.1.1 无符号数的表示方法

对于n位二进制数,则其表示范围为 ,将10进制转化为2进制(16进制)即为计算机中的存储。

1.2.1.2 符号数的表示方法

基本概念:

  • 机器数:一个符号数(包括符号位)在机器中的一组二进制数的表示形式就叫做机器数。
  • 真值:机器数所表示的数值称为该机器数所表示的真值。
    具体数值取决于符号数的实现方式,故举例见下方章节。
1.2.1.2.1 原码

尽管当前计算机中实际使用的为补码,但是我们先从原码讲起。

将二进制数最高位当成符号位,正数为 0 、负数为 1 ,其余位数为数值的表示形式即为符号数的原码表示,例如:

  • 0110 0100 = +100
  • 0111 1111 = +127
  • 1110 0100 = -100
  • 1111 1111 = -127

则其特性为:

  • 位原码能表示的数值范围为
  • 原码拥有"+0"和"-0"两个"0"

存在的缺陷:

  • 计算机进行加减运算时需要两套逻辑处理,需要分别实现加法器和减法器,而减法器的硬件实现较为麻烦。
  • 少表示一位数。
1.2.1.2.2 反码

对于正数,其反码与原码相同;而对于负数其二进制表示是其对应正数的反码表示,例如:

  • 0110 0100 = +100
  • 0111 1111 = +127
    则对应的负数为:
  • 1001 1011 = -100
  • 1000 0000 = -127

则其特性为:

  • 位反码能表示的数值范围为
  • 反码拥有"+0"和"-0"两个"0"
1.2.1.2.3 补码
1.2.1.2.3.1 补码符号数的表示方法

补码是当前计算机使用的符号数表示方法
其核心思想是找一个"无符号正数",使得其加减运算性质和这个"有符号负数"一致。具体规定如下:

  1. 正数的补码与其原码一致。
  2. 对于负数,其机器数为正数的机器数按位求反再加1(此步骤的+1不溢出到符号位)。
    例如:
  • +100 = 0110 0100
  • +127 = 0111 1111
  • -100 = ~(0110 0100) + 1 = 1001 1100
  • -127 = ~(0111 1111) + 1 = 1000 0001
  • -128 = -127 - 1 = 1000 0000

则其特性为:

  1. 对于同样的 位,相较于反码而言,补码可以多表示一个数():
    1. 对于 位补码,其能表示的数值范围为
    2. 对于 位补码,其可以表示 个不同的数。
  2. 补码所表示的正负数之间可以直接进行与无符号数规则一致的二进制加法运算并可以保证结果正确。具体可见下一子章节。
    1. 本质为补码涉及时的核心思想(找一个"无符号正数",使得其加减运算性质和这个"有符号负数"一致)。
  3. 补码的机器数的数值中负数的机器数大于正数的机器数因此整数大小比较较为不便(可见移码章节的表格)。

则其优点为:

  1. 加减运算只需要使用加法器即可实现,不需要额外的减法器。

存在的缺陷有:

  1. 负数的机器数大于正数的机器数,整数的大小比较不方便。
1.2.1.2.3.2 补码符号数的加、减运算

如上文所述,使用补码原则可保持符号数的加减运算直接按照二进制进行运算,具体举例如下:

  1. 普通运算:
    Pasted image 20240331171254.png
  2. 正负数和运算:
    Pasted image 20240331171315.png
    Pasted image 20240331171331.png
  3. 溢出情况:
    • 向上溢出:
      Pasted image 20240331171354.png
      此时向上溢出( OF=1 ,为下一章内容),
    • 向下溢出:
      同样的,对于 -64-68 ,其结果为:
      1100 0000 + 1011 1100 = 0111 1100 = 124
      即:
1.2.1.2.4 移码

移码在补码的基础上将补码的符号位取反,其优点是解决了负数机器数大于正数机器数的问题

真值 补码 补码机器数 移码 移码机器数
-128 1000 0000 128 0000 0000 0
-127 1000 0001 129 0000 0001 1
... ... ... ... ...
-1 1111 1111 256 0111 1111 127
0 0000 0000 0 1000 0000 128
1 0000 0001 1 1000 0001 129
... ... ... ... ...
126 0111 1110 126 1111 1110 255
127 0111 1111 127 1111 1111 256

则其特性为:

  • 移码解决了负数机器数大于正数机器数的问题,方便了计算机的数值比较。
  • 移码只能用于表示整数。
  • 移码所能表示的数值范围与补码相同。

移码的另一种理解方式:

  • 移码可以理解为:移码=真值+偏置值。
  • 在本规则的设置种,偏置值为 。但是在IEEE 754中有不同的定义和使用。

1.2.2 定点数相关拓展

1.2.2.1 加法器与减法器

1.2.2.2 C语言及其类型转换

1.2.3 浮点数的表示与运算

1.2.3.1 浮点数的表示

一般来说,浮点数的表示格式为:其中:

  • S:符号位,取值0或1
  • M:尾数,是一个二进制顶点小数,通常用原码或移码表示决定了计数的精度
  • R:隐含基数,通常约定为2、4、16等
  • E:阶数,是一个二进制定点整数,通常用补码或移码表示决定了计数的范围

浮点数的表示范围:
Pasted image 20250227150402.png

  • 正负下溢:
  • 正负上溢:

1.2.3.2 浮点数的规格化

讨论两种情况:

  1. 尝试以十进制的科学计数法表示 304258614721 ,并规定尾数占4位,阶数占2位,则该数字可以被如下的几种方式表示:

    • 明显地,第一种的精度最高,想要获得该形式只需要让尾数的最高位保持为有效位(即非零位)即可,这个过程叫做左规
  2. 现在假设某浮点数经过运算后得到 ,那么需要额外的信息标记小数点的位置,所以不妨直接规定成小数点在第一位的后面,节省空间给其他部分。这个过程就叫做右规

而在二进制表示中,有效位一定为 1因此通常将该位内存省略(如IEEE 754)。

1.2.3.3 IEEE 754

现在常用的浮点数标准为IEEE 754,在该规范中,上述浮点数格式为:

类型
总位数 符号位 阶数 尾数 隐含基数
短浮点数( float ) 32 1 8 23 2
长浮点数( double ) 64 1 11 52 2
临时浮点数( long double ) 80 1 15 64 2

其中:

  • 阶码使用移码表示,其偏置值为 ,即:移码=真值 + 为阶数位数。
  • 尾数部分使用原码表示,隐含了首位的 1.
    其在内存中的布局为:
    Pasted image 20250227153515.png
1.2.3.3.1 阶码规范(以float为例)

本章节以 float 为例。
首先,阶码的移码偏置值被定义为 ,在 float 中为127,其补码真值表为:

真值 移码 移码机器数
备注
-127 0000 0000 0 二进制全 0 ,预留于特殊表示
-126 0000 0001 1
-125 0000 0002 2
... ... ...
-1 0111 1110 126
0 0111 1111 127
1 1000 0000 128
2 1000 0001 129
... ... ...
127 1111 1110 254
-128 1111 1111 255 二进制全 1 ,预留于特殊表示

则有两个特殊的移码:

  • 移码二进制为 0000 0000 时对应真值为 ,用于特殊表示
  • 移码二进制位 1111 1111 时对应真值位 ,用于特殊表示
    因此阶码的表示范围为 ,即
1.2.3.3.2 尾数规范(以float为例)

本章节以 float 为例。
首先需要注意,IEEE 754已经隐含了浮点数的规格化

  • 尽管尾数为23位,但是实际上表示了24位的信息,第一位恒为 1
  • 此外,尾数的小数点一定在隐含的 1 后面,即默认携带了 1. 前缀
    因此在计算的时候,在数值前加上 1. 后使用原码规则进行计算即可。
1.2.3.3.3 特殊表示

在阶码规范中预留了两个特殊表示,其对应的定义和用途如下:

  1. 阶码全 0 ,且:
    1. 尾数全 0 时,表示真值 ,可以用于表示正负下溢
    2. 尾数不全为 0 时,表示非格式化数其依旧有具体的数值含义此时取消尾数的 1. 前缀进行数值计算即可得到其所表达的数值用于补充规格化所带来的小值的表示域缩小,可以用于平滑计算等。
  2. 阶码全 1 ,且:
    1. 尾数全 0 时,表示真值
    2. 尾数不全为 0 时,表示非数值 NaN (Not a Number)。
1.2.3.3.4 求值计算

在判定特殊表示后,按照下式转换即可:

1.2.3.3.5 加减运算

浮点数加减运算的步骤:

  1. 对阶:将阶数更小的数值向阶数更大的对齐(方便计算机硬件处理)
  2. 尾数加减
  3. 规格化:令尾数的小数点在第一位有效数字后
  4. 舍入:使用四舍五入等方式保留尾数的有效位数
  5. 判溢出:判定阶码位数是否超限

对于二进制来说,通常要增加一个格式转换的过程。例如:

已知:,进行二进制浮点运算 。假设浮点数格式为阶符2位、阶数3位、数符2位、尾数9位。

则有:

  1. 转换格式:
    1. 拆出分子分母:
    2. 将分子分母分别转换为二进制和2的幂:
  2. 对阶:
  3. 尾数加减:
  4. 规格化:
  5. 舍入:尾数无需舍入
  6. 判溢出:未溢出

1.2.3.4 双符号位与溢出检测(了解)

1.3 十进制数与字符的编码

1.3.1 BCD码

BCD码就是用四位二进制表示一位十进制,且浪费6个字符空间,如下图所示:
Pasted image 20240331172256.png
对于任意n位十进制数,均需要4n位二进制表示,例如压缩BCD码

  • 9521 =
  • 13.25 =

而BCD码可以分为压缩BCD码和非压缩BCD码两种:

  • 压缩BCD码:一个Byte(8位)用于表示2位10进制,例如:
    • 9521 =
  • 非压缩BCD码:一个Byte(8位)用于表示1位10进制(更浪费了),例如:
    • 9521 =

1.3.2 BCD码的运算及其调整

就注意需要对非法BCD码进行进位即可,例如

  1. 正常BCD运算
    Pasted image 20240331173039.png
  2. BCD进位调整:
    Pasted image 20240331173046.png
    (不如先用十进制计算,再转BCD)

1.3.3 字符编码

字符编码即经典ASCII编码。需要注意的有:

  1. 使用符号 ' ' 将字符括起来可以表示该字符的二进制值,例如:
'A'  = 41H
'5C' = 3543H // 注意扩两个字符则是2Byte,且C语言支持扩多个字符
  1. 由于使用的是经典ASCII表,只有128个表示,故最高位可以用于做奇偶校验:
    1. 使用奇校验:操作最高位使得该Byte中 1 的数量为奇数个。
    2. 使用偶校验:操作最高位使得该Byte中 1 的数量为偶数个。