整数的表示

高优先级

本章是每年必考的重点,补码有符号数 和 无符号数 每年都会在选择题考查,也会在大题直接或间接考查,并且本章是组成原理的基础,必须 完全掌握

BCD 码

BCD(Binary-Coded Decimal)码是一种 二进制编码方法,用于表示 十进制数字。每个十进制数字(0-9)都使用 四位二进制数字 表示。

BCD 码的基本思路是 单独表示每个十进制数字的二进制值,而不是像传统的二进制数系统那样对整个数字进行编码。

单独表示一位十进制数

例如,在传统的二进制编码中,数字”19”会表示为 10011,但在 BCD 中,它被表示为两个独立的数字:“0001”(对应于 1)和“1001”(对应于 9)

因此十进制 用 BCD 码表示为

BCD 编码在某些应用中是很有用的,特别是在需要与 十进制界面 进行交互的地方,如 数字显示 或某些早期的计算机系统。尽管它不如 纯二进制编码 效率高,但它简化了与十进制数据的转换过程。

整数的表示与运算

无符号数

无符号数(unsigned number) 是计算机中一种整数类型,只能表示 非负数(包括 0 和正整数),不包含负数。

  • 纯二进制表示

在非负数中,数字中的第  位的大小就是  。
对于一个  位 无符号数  ,假设它的第  位表示为 

则该数字的二进制表示为 

对应的十进制数为:

纯二进制表示范围

根据以上公式可知,一个  位纯二进制表示的:

  • 最小值: 

  • 最大值: 

  • 表示范围: 

注意

需要注意的是,无符号数 就是没有符号的二进制表示,它不像 有符号数 的表示,有一个 补码 这个专有名词。但是我们一般可以叫它 纯二进制 或 无符号数二进制表示

有符号数

使用补码表示,一个8位有符号整数的范围是 共256个,与无符号数个数一致

除了零的表示唯一以外,数据位和符号位还可以一同参与运算,加减法在计算机中都算做 加法电路。

位有符号整数的表示范围为

补充 八位补码将原码 表示为 即:

上述提及的补数特点均可以迁移到补码中去 !!!

模的大小决定了 负数 的补数大小。

Caution

,这种写法是真值表示;做题时将 -101 改成 原码表示 1101 后再转化到补码的表示形式 1011

补码定义

现代计算机中都采用IEEE 754标准表示浮点数,定点小数采用 原码 表示,上述的补码定点小数一般不会出现

做题技巧

最值问题

讨论 补码的时候 ,我们只讨论 数据部分的 大小,其表示大小和真值表示一致

讨论 移码的时候, 我们需要整体去看, 全零就是最小的,全一就是最大的

补码的特质

  1. 在同为负数的情况下,补码和反码 的数据部分越大 ,其表示的 负数值也就越大(这里是接近0的意思)

  2. 如果题目是求 补码的最小值 (负数) ,则数据部分应该最小

  3. 补码的 补码 就是原码

  4. 如何快速将原码变成补码? 答:扫描法 找到负机器数中最后一个 ,再对该 位前面所有位进行反转

移码的特质

移码 作为一个表示的编码方式,其优点十分多(做题目时经常用到)

  1. 移码 的 符号位 一反 得到的就是 补码

  2. 移码 越大 (包含符号位) 真值越大

  3. 移码 的覆盖范围是

  4. 真值表达式:

注:移码只能表示 定点整数

类型转换

中优先级

常在选择题考查,其实就 三点:整形和浮点数的转换,不同长度类型的转换,隐式和显式的转换。

有符号整数和无符号整数

当 有符号整数 和 无符号整数 之间相互转换时,二进制数据 不变,只是改变了变量(或数字)的类型。

首先需要了解 有符号整数(int)和 无符号整数(unsigned)这两个类型:

  • int:使用 补码 来存储数据。
  • unsigned:所有位,包括最高位,都用于表示数值,表示非负数。

注意

在现在的 64 位计算机中,一般 int 表示 32 位 有符号整数unsigned 表示 32 位 无符号整数
由于 int 和 unsigned 在不同体系计算机中行为不同,所以 C 语言库中也自带 int32_tuint32_t 这种类型来表示特定位数的 有符号 和 无符号 整数,并在各计算中行为一致。

这里为了方便说明,以 8 位 有符号整数 和 无符号整数 为例:

  • 8 位 有符号整数

    • 表示的范围为 -128 ~ 127
    • 最大数为127,对应的二进制为0111 1111
    • 最小数为-128,对应的二进制为1000 0000
  • 8 位 无符号整数

    • 表示的范围为 0 ~ 255
    • 最大数为255,对应的二进制为1111 1111
    • 最小数为0,对应的二进制为0000 0000

当 int 和 unsigned 进行 类型转化 时,位模式 不变,可以理解成计算机存储单元中的二进制表示没有变化,只是从程序层面阐述该二进制数据的方式变了,如下图所示:

整形和浮点数

较难

在计算机中,整形(short, int, long)和 浮点数(float, double)之间可以相互转换,但是在转换的过程中可能出现 精度丢失 或 数据溢出

整形转浮点数

如果一个整数被转换为浮点数,其结果是否会产生 精度丢失 取决于整数的大小是否超过浮点数可以精确表示的整数范围。
但当整数足够大时,转换可能导致 精度损失

比如对于 float 类型,其尾数为 23 位,它可以精确表示的整数范围为 (−224,224) ,如果一个 int 类型的数字在这个范围内,则将其转换为 float 时 不会丢失精度

但是如果 int 类型数字超出这个范围且低 8 位不全为 0 的话,则将其转换为 float 会有 精度丢失

浮点数转整数

当 浮点数 被转换为 整数 时,小数部分会丢失,因为 整数 不能表示小数。

此外,如果 浮点数 超出了 整形 的表示范围,转换可能会 溢出 或产生未定义行为(取决于语言)。

不同长度的类型转换

总结一下不同长度的 整数 和 浮点数 的 类型转换 规则:

  • 整数和整数
    • 较小的 整数类型 被转换为较大的 整数类型 时,高位会被自动填充为 0 或 1,不会有数据丢失。
    • 较大的 整数类型 被转换为较小的 整数类型 时,高位会被自动截断,可能有数据丢失。
  • 浮点数和浮点数
    • float 转为 double 时,不会有 精度丢失double 转为 float 时,可能有 精度丢失

分析总结

定点数的类型转换过程,若涉及到字长变化,则触发两个基本操作:位截断位扩展

位扩展 的具体扩展方式 根据源数据的 符号性 分为:

  • 零扩展 : 用于无符号数,在高位补
  • 符号扩展:用于补码表示的有符号数,高位填充符号位

符号扩展

举例 这个数据是否带符号,需要看 编程语言中 用什么数据类型表示的
假如是 short t = -6;,则发生位扩展时 int t;,得到的就是

类型转换

在编程中,类型转换 指的是将一种数据类型转换为另一种数据类型。主要分为两种:

  • 隐式类型转换(Implicit Type Conversion)(也称为 类型提升,Type Promotion)
  • 显式类型转换(Explicit Type Conversion)(也称为 强制转换,Type Casting)

隐式类型转换

在 C 语言中,当算术运算、赋值和比较表达式中涉及的多个变量类型不同时,如果没有显式指定类型,编译器会自动进行 类型转换

/* 隐式类型转换 */
int i = 5;
float f = 2.5;
float result = i + f;  // i 被隐式转换为 5.0 然后进行计算

你在一个表达式中混合使用 int 和 float 时,C 语言会自动进行 类型转换 以使得表达式可以正确计算。通常情况下,低精度 类型会被 提升高精度 类型,即 int 会被转换为 float

显式类型转换

也可以使用 类型转换运算符 显式地转换一个类型为另一个类型。

/* 显式类型转换 */
int i = 5;
float f = 3.2;
int result = (int)f + i; // f 被显式转换为 3,然后与 i 相加

显式类型转换 会按照你指定的方式进行,在此过程中可能会发生 精度缺失

运算方法和运算电路

回顾视频

整体看完,对第二章的运算电路逻辑能有一个全面的回顾

基本运算部件

半加器

最基本的加法单元是 半加器(Half Adder)。它有两个输入,一个是加数,一个是被加数,并有两个输出,一个是和,一个是进位。

如上图所示,通过对两个输入(A 和 B)进行 异或(XOR)计算,可以得到 (S)。
通过对两个输入进行 (AND)操作,可以得到 进位(C,即 Carry)。

半加器 的主要限制是它只能对两个位进行加法,并且不能处理来自低位的进位输入

半加器的时间延迟为

没啥卵用

全加器

全加器(Full Adder)是 半加器 的扩展,它加上了前一位的 进位(Cin)作为第三个输入,并有两个输出,一个是 (S),一个是 进位(C)。

半加器用于处理两个位的简单加法,而 全加器则可以处理包括 进位 在内的三位加法,是构建复杂加法电路的基础。

逻辑表达式的推导过程可以对 真值表 中的有效变量进行 卡诺图、异或门逻辑表达 化简得到

全加器的时间延迟为

加法器 的基础阶段

串行进位加法器

图不给了,就是很老实的从 一步步 的计算出 ,最后算出所有 和位 与 进位

位串行进位加法器 的时间延迟为

并行进位加法器

根据下列递推公式 进行 电路设计


其中 分别表示的是

如图所示:我们可以得到其逻辑电路

位并行进位加法器 的时间延迟为

各类标志位

一般题目 会问你 无符号数 的 OF ,虽然对于无符号数来说,OF没任何鸟用;但是在运算电路中 OF 都会被计算出来放到一个寄存器中

这里的最低进位 如果是加法运算 就是 ,若是减法运算则是

18统考题,解释说:减法只需看借位,加法看进位

定点数的移位运算

逻辑位移

逻辑移位将操作数视为 无符号整数 。逻辑移位的规则:左移时,高位移出,低位补 。若高位的 移出,则发生溢出。右移时 ,低位移出,高位补

算数位移

算数移位将操作数视为 有符号整数 。算数移位的规则:左移时,高位移出,低位补 ,若移出的高位与 符号位 不同,则发生 移位溢出 。若高位的 移出,则发生溢出。右移时 ,低位移出,高位补 符号位,若低位的 移出,则 影响精度大小

重点

移位运算的 溢出精度缺损 考到的概率比较大

循环位移

操作对象为 无符号数

将无符号数以二进制形式中的各个位向左或向右移动,将被移出的位重新放在另一端上,形成循环

由于很多处理器架构中,循环移位指令会影响状态寄存器中的 进位标志 CF 位,CF 标志位用于标识在执行算数或逻辑操作时是否发生了进位。

根据 CF 标志位 是否加入循环位移过程,分为 带 CF 标志位 位移和 不带 CF 标志位 位移 两种方式!

主要应用于:加密算法、哈希函数、优化算法

不带CF标志位

带CF标志位

定点数的 加减乘除 运算

加、减运算电路

在计算机中,无论是有符号数还是无符号数的加减运算,均采用同一套硬件电路实现,即”一套电路,两种语义

计算机中没有专门的减法电路,因为 补码 的 减法 可以被转换为 加法 操作:

以下电路可以实现操作数 A 和操作数 B 的 加减法

电路图解释

如果是计算 A+B 的话,将 Sub 设置为 0,直接对 A 和 B 进行 加法计算。

如果是计算 A-B 的话,将 Sub 设置为 1,会对 B 进行取反加一,得到,然后使用 加法器计算 A + (-B) 即可。

Sub 与 Cin

这里 设为 ,实际上就是对 ,这里的 是啥,取决于做的是 加法 还是 减法

判断溢出

重要

一定要区分 补码溢出和 无符号数溢出,这两个是一定要分清楚的

方法一

加深理解

方法一 只能判断 两个符号位 相同的 操作数 在 相加时 的结果是否溢出

上述的加法并不是说只有 时才算数;相反,因为计算机中只有加法器,所以当 时,内部运算部件将 取反加一后的 作为新的操作数

方法二

注意

这里 符号位进位 是由 数值位的进位 两个符号位 相叠加后的结果

方法三

注意

变形补码一般也叫做 模 $4$ 补码 ,符号位一位的普通补码叫做 模 补码

变形补码不影响原码转换到补码

逻辑表达式

太野了,这里使用的同上面 方法二 模 2 补码 的一样。

真题解读

小技巧

1


此时,直接利用十进制计算结果,可以快速判断出其正负从而排除错误答案

2


根据选项,可以判断直接计算是最快解决问题的步骤,算x,y的真值反而浪费了时间


乘法运算电路

计算机中没有乘/除运算电路,但是可以利用加法和移位相结合的方法来实现乘/除 运算。

二进制中 左移一位 乘二, 右移一位 除二;

说实话,王道 这个书对新手真是太友好了,但是内容也是真的屎

二进制乘法 与十进制乘法的手工计算方式类似:

乘法移位的原因是 让 位积 的 权值位 对齐,以便相加

由于寄存器空间宝贵,因此对上述浪费空间的手工算法进行了优化,将多个位积转变成一个个新的部分积,直接原空间上做计算;

通过硬件的方式串行地模拟手工计算的方式,无符号数的 乘法硬件电路 如下图所示(了解即可):

其思路是通过 右移 和 加法,每次输出 乘法结果中的一位。

无符号数乘法运算

控制逻辑计数器 里的大小和 乘商寄存器 大小一致 !

原码一位乘法的运算原理

原码(一位)乘法的特点是符号位与数值位分别处理

  1. 乘积的符号位由两个乘数的符号位异或得到

  2. 乘积的数值为是两个乘数绝对值的乘积

操作 2 与无符号数的乘积过程一致,直接看上面的图片即可点击跳转

具体流程图如下,该图同样适用于无符号数的乘法

如果每次 根据乘数中的两位来计算位积 ,则位积的数目能减少一半,因此循环累加次数将减少一半,可以大大提升乘法的运算速度,这种乘法称为 二位乘法

无符号阵列乘法器

图中的每一个 FA 全加器进位 加到下一层位积,理解成本层的 新位积 与 下一层位积相加

优化

  1. 将第一层的全加器改为半加器,第一层不会有进位,直接白赚 的时间延迟
  2. 将最后一层的 位串行进位加法器改为 先行进位加法器,加快多少你别问!

Booth 算法

补码阵列乘法器

图片理解

**间接**补码阵列乘法器,首先对 两个乘数 进行求补,接着到 无符号阵列乘法器 乘完后,得到 绝对值之积 ,又根据两个符号位异或的结果对绝对值之积 再进行一次求补;

直接补码阵列乘法器 (Baugh-Wooley 算法) 实际上能省去先求绝对值之积,再求补码的繁琐步骤,直接一步到位得到补码乘积

求补电路

更快的电路设计,思想来自扫描法求补码

从这里也能看出,电脑使用二进制对于硬件设计来讲也带来了极大的方便

只要有一位 是 1,异或的其中一路就是1,上面所有位 或 的异或结果都是其相反数


除法运算电路

二进制 除法在计算机中的实现与我们在十进制中所执行的传统 除法类似。

Done

不难观察到 如果商 , 每次减去后再出现的被除数 都是以 4位 一个的形式出现的 ,这是为了使中间余数除数寄存器的位宽一致,从而能够通过 4 位减法器进行大小比较和减法运算。

除法的本质是减法

二进制 除法可以被总结为如下步骤:

  1. 准备
    • 将被除数和除数都转换为二进制形式。
    • 写下被除数和除数,类似于十进制除法的长除法形式。
  2. 除法
    • 从被除数的最高位开始,与除数进行比较。
    • 如果被除数当前部分大于或等于除数,则商为 1,否则商为 0。
    • 如果商为 1,则将被除数当前部分减去除数,并将差写在下面。
    • 将被除数的下一位数字移下来,与差组成新的被除数部分。
    • 重复上述步骤,直到被除数的每一位都被处理完毕。
  3. 余数
    • 最后一次减法运算得到的差即为余数。
    • 如果最后一次减法得到的差是 0,则表示整除,没有余数。

简单的 除法电路结构也是通过模拟以上过程实现(了解即可):

Caution

两个 位无符号数相除 不会发生溢出 因为被除数最大为 ,最小的非零除数为 ,此时商为最大值,即为 ,恰好可用 位无符号数表示。

在 除法电路 中,在每次迭代中我们将当前 余数 左移一位,并引入 被除数 的下一位,然后执行 余数减去除数 的操作,接下来通过条件判断检测 减法结果 的符号以确定  的当前位。

在每次迭代中,我们可以输出 除法结果 中的一位,重复直到处理完所有位后,可以得到  和 余数 的结果。

原码除法运算

恢复余数法

不溢出 需要遵守的法则

  1. 除数
  2. 定点小数:|被除数| < |除数|
  3. 定点整数:|被除数| |除数|
举例

不恢复余数法

核心

, 在恢复余数法中的表示为:

原码的乘除基本上都要先取 绝对值 转换成无符号数计算

其次 原码四则运算中 符号位 和 数据位 是独立计算的,

举例

计算细节

  1. 如果两个小数(整数)位数是对齐的,第一个加法器中直接相加不用左移
  2. 最后一个加法器中,如果结果是正数,则该正数就是余数;若结果为负数,需采用恢复余数法:再加上一个 ,不用左移。

牢记,原码乘除时,先绝对值,再取反加一

溢出

你难道不好奇原码除法的溢出是什么形式的吗,只要你算出来的 绝对值商里的第一位() 是 开头的,这就是一个无效 商

现实中的定点小数除法,要求被除数必须小于除数(),这样商才能保持在 之间。如果绝对值除法算出了 ,硬件通常会抛出一个“溢出中断”,此时这个商在小数运算中是无效的。

补码除法运算

因为大部分书中采用不恢复余数法,所以这里讨论的都是 不恢复余数法 的!

补码除法将 符号位 和 数值部分 一起参加运算,商符是在求商的过程中自然形成的 。因此,补码除法的运算方法没有原码除法的运算方法直观,需要解决以下3个主要问题:

  • 如何确定商值
  • 如何确定商符
  • 如何得到新余数

此处,记载了除数不溢出的条件,利用不溢出条件可以推出:如果商有效,则商符在补码除法运算中是确定的

举例

黄字 重点,左移一共 次,(商也左移了一位),不同于 原码绝对值的 除法部分 !!!

首位商用于判断是否溢出,商符形成 图上 也标明了;末位商置 ,这是为什么?

总结

硬件实现上 同 补码阵列乘法器,也有 补码阵列除法器


浮点数的表示与运算

通常,浮点数(IEEE754)表示为:

实数的二进制表示

字面值转二进制

举个实际的例子,将 1.2 转换为二进制表示。

整数部分 1 的二进制是 1。
小数部分 0.2 的二进制表示是一个无限循环小数。通过不断乘以 2,可以得到近似的二进制:

  • 0.2 × 2 = 0.4 → 整数部分 0
  • 0.4 × 2 = 0.8 → 整数部分 0
  • 0.8 × 2 = 1.6 → 整数部分 1
  • 0.6 × 2 = 1.2 → 整数部分 1
  • 0.2 × 2 = 0.4 → 重复…

于是,1.2 在二进制中近似为 1.0011001100110011...

上述 机器数称作 定点小数 ,而定点小数主要用于表示浮点数的尾数

普通浮点数

最大的特点就是 尾数的数符跟在阶码后面,并且尾数不自带 中的 1
其公式可以表述为:

例题:

易错点 将浮点数的尾数同 IEEE754尾数的定义搞混

浮点数的规格化

算细枝末节了,但是值得一看

Caution


本题中的阶码是正数,所以不用三大码转换;但是尾数是负的,因此数值部分需转换

浮点数变化 是对 阶码尾数 分别进行的,综合搭配有四种变化可能!!!

其中阶码 可表示成:原码 反码 补码 移码 ;尾数 可表示成: 原码 补码 反码

阶码多一个 移码可以表示

规格化中,尾数的第一个数值位一定是

例题

Missing

错了 需要记忆,浮点数规格化可以省去不必要的 位置,将核心部分提前留出空位

其次,上述选项表述的意思是,规格化后可以表示精度更高的数字

本题的一个 特殊点在 上,一般不加逗号或者符号,都默认表示的是真值

本题的难点在于不知道基数变化的情况下对应的规格化尾数是什么形式
因此,需要重点记忆对应 的 左规右规定义

IEEE 754

上述 浮点数 存储方式的缺点在于如果要表示比较大的数,就需要比较多的二进制位数,比如对于 5×2100 就需要 103 位。IEEE 表示 就解决了这个问题,在 IEEE 表示 中,浮点数 V 被表示为  ,其中 s,M,E 的含义如下:

  • S  为 符号位
  • E  为 指数部分
  • M  为 乘法因子

IEEE 754 标准 是定义浮点数表示和算术的国际标准,它定义了多种不同精度的浮点数格式,但最常见的是 单精度 single precesion(32 位)和 双精度 double precesion(64 位),浮点数分为 s符号位)、exp阶码)、frac尾数)三个部分存储:

还有一种格式:临时实数 (80位),阶码E取15位(含一位阶符), 尾数M取65位(含一位数符)

浮点数定义

符号位() 就不必多说了

阶码() 就是

尾数() 本身就自带一个 1——1.xxxx,.xxxx由后面23位或是52位尾数表示了

浮点数表示范围

常用对照表格,需要记忆

浮点数加减运算

尾数规格化一定要有,如果发现阶码全 ,说明这个结果是一个非规格化小数,用非规格化表示

你有想过 阶码作为移码 其 机器数的值 是加上 偏移值 还是 减一个偏移值?

减去 偏移值

就近舍入

BOK 就近舍入

  1. 找出 左右相邻 的两个可表示数

  2. 判断 大小

  3. 截断数与 进行比较

  4. 确定最近相邻数

注意

在浮点数加减中,需要保留 左规或右规 后 多出来的高三位尾数() 用来判定舍入

机器的判断流程; 舍入到偶数 中的偶数,又叫做末位为0 的相邻数

大数吃小数

当 两浮点数 阶码相差超过尾数宽度(24/53位)时,小阶操作数在右移后有效位全部丢失,导致加法结果等于大阶操作数的情况,一般情下应该要到 25/54位(舍入)

浮点数的乘法运算

浮点数的除法运算

数据的宽度和存储

数据的宽度和单位

  • 比特(bit、b) 是最小的信息单位,表示一个二进制位(0 或 1)

  • 字节(byte、B) 是基本的存储和寻址单位, 1 字节 = 8 比特

  • 字 (word) 也是常用的数据组织单位、是由体系结构定义的逻辑单位,通常用于表示整数、地址等基本数据类型的宽度

  • 字长 (也称机器字长) CPU 内部整数运算的数据通路宽度,通常等于通用寄存器的宽度

数据的存放

发现华点

这里的 字地址字节地址 ,在后期的 cache 映射中 是非常重要的概念

重点关注

大端存储

存储在低地址, 存储高地址,字节顺序与数据的找标准十六进制书写顺序一致。

小端存储

存储在低地址, 存储高地址,字节顺序与数据的找标准书写顺序相反。

总结

”边界对齐“方式存储

在字长 32 位的系统中,字节可位于任意地址,半字地址须为 2 的倍数,字地址须为 4 的倍数;因为要满足 CPU 可以在 一次访存 下读取完整数据。

否则(假如数据跨越两个存储单元),则需两次访存还要拼接字节,为了满足对齐,通常需要填充空白字节。

这种 ”空间换时间“ 的策略 虽略微增加内存占用,但能大幅提升访问速度。

总结

做题技巧

对地址映射要从 下标开始,题目中给定的首地址就是第一个元素的存储地址了!!!

给定一个初始地址,若要求第 个字节的地址,直接将 加在初始地址就是答案了

易混淆点

在相同位数下,定点数 通常比 浮点数 能表示更多的有效数值

因为 位编码 最多能表示 个不同比特模式 并且 浮点数 还有部分编码表示 等特殊值,实际可表示的有效实数个数少于


无符号数溢出是因为运算结果大于等于 时,硬件仅保留了低 位(结果对 取模),舍去高位,导致截断后的值不等于真实结果;

运算器中,通常用 进位标志(CF)来检测无符号数溢出

错题


补充 当一个有符号数(i)和一个无符号数(j-1)进行比较时,C 语言会自动将有符号数隐式转换(提升)为无符号数

在计算机底层,无符号数的“大小”比较(低于/高于)是根据 CF(进位/借位标志)ZF(零标志) 来判断的

OF(溢出标志) 是给有符号数运算准备的,在这里不适用。

过于逆天的题目


补充 整数与整数运算,得到是整数;但是实数与整数运算得到的是实数