2.数据的存储

数据的存储

1.整数的存储

1.进制间转换

  • 数据在计算机中是以二进制数表示的,1位二进制数表示1bit(比特),1byte(字节) = 8 bit

QQ截图20221206105904

对于十六进制和二进制转换,可以记住 A(1010)、 C(1100)、F(1111),这三个数然后通过这三个数来记住 B = A + 1、D = C + 1、E = F - 1, 记住这些就可以快速计算出对于的值

进制转换:对于 2 -> 16 , 16 -> 2 只需要记住 4个二进制对于 1个十六进制即可,其他进制转换到10进制直接展开即可,其他进制转换2进制,进行 % 2 + 余数,知道无法在进行取余即可,然后将所以数倒排即可

例如 10进制 10 转换成 2进制数
	10 / 2 = 5	10 % 2 = 0;   0
	5 / 2 = 2   5 % 2 = 1;    1
	2 / 2 = 1   2 % 2 = 0;    0
	1 / 2 < 1   1 % 2 = 1;    1
所以说, 10的二进制数表示就是1010

2.无符号数与有符号数

1.无符号数

QQ截图20221206110926

  • 对于无符号数来说,是使用原码进行表示,其每一位bit表示对于数的正权值,例如1010 = 1 * 2^3 + 0 * 2^2 + 1 * 2^ 1 + 0 * 2^0 = 10
  • 最值问题:对于无符号数的最值其实就是所有的正权值数的累计和,即是2^n - 1

2.有符号数

QQ截图20221206110935

  • 对于有符号数来说,都是使用补码来进行表示,其重要的就是最高位是负权值表示,这点非常重要,例如 -5 = 1011,-10 = 10110

  • 对于有符号数来说,有最大值和最小值,MAX = 0 + 2^(n - 2) + …… + 2^0 = 2^(n - 2) - 1,其MIN就是最高位为1,其他位为0,MIN = 2^(n - 2)

3.有符号数和无符号数之间的关系

QQ截图20221206112347

有符号数和无符号数来说,在计算机的存储方式其实都是一样的,只是在解释方式不同而已,所以在使用无符号数和有符号数解释时要注意使用不同的解释方式,即原码和补码的解释方式

4.特殊数

在有符号数和无符号数中,全1的数字是非常特殊的

  • 对于无符号数来说,全1代表着无符号数的最大值
  • 对于有符号数来说,全1代表着-1,无论是多少位都是代表着-1

3.数据溢出和移位操作

1.数据溢出

  • 其本质上就是数据运算时出现结果不符合预期值的情况,在此讨论有符号数和无符号数的溢出情况
3.1 无符号数的溢出
  • 对于无符号数来说,其值都是大于0的,当进行计算出现两者相加小于原来的加数时就出现溢出的情况

    对于两个4位二进制无符号数1100 + 1100 = 1000, 其值小于原来的加数

3.2 有符号数的溢出
  • 对于有符号数来说,只有两个数符号相同时才会出现溢出的情况,所以直接看同正或者同负的情况

QQ截图20221206113659

当同为正且出现溢出时,结果值将会变成负值(正溢出);当同为负且出现溢出时,结果值将会变成正值(负溢出)

注:计算机中会将减法转化成加上一个负数

2.移位操作

2.1 字节序存储方式

首先先看一下数值在计算机中的存储方式,其分为 小端字节序 和 大端字节序

QQ截图20221206114516

  • 其用一句话来表示就是:大端法将高位放到低地址处,低位放到高地址处;小端法将高位放到高地址处,低位放到低地址处
  • 注意:向67在小端法中放入内存中并不会变成76,其数值是不会跟随存储方式改变
2.2 移位
  • 移位操作分为 左移(向左) 和 右移(向右) 操作

左移:对于有符号数和无符号数来说,都是在右端补0

右移:对于无符号数来说,执行逻辑右移,其就是在左端补0;但是对于有符号来说,其左端要补的数字就是最高的负权值的位数 1 / 0,执行的是算术右移

QQ截图20221206115557

那为什么对于有符号数的算术右移是在左端补充的是负权值的数呢?

  • 当负权值上面的数为0时,其就是和逻辑右移一致
  • 当负权值上面的数为1时,我们先来看右移一位时的情况,原数为 -2^(n - 1) + 0 + …… + 0, 当我们右移一位时,其值变成了 -2^(n) + 2^(n - 1) + 0 + …… + 0,对比两个数我们会发现两者的值并没有发生改变,所以我们就可以推广到右移任意位数
2.3 移位及加减代替乘法
  • 对于一个整数来说, << k 就是乘上 2^k ,同理 >> k 就是除以 2^k (注意k为非负数)

QQ截图20221206115606

在计算机中的处理数据运算时,通常会将乘法转化成对于数倍数的 加减法,在计算机中加减法的运算执行时间少于乘法,所以利用位移运算可以将其进行转化

4.常见数据类型的范围

  • 在题目中经常涉及到数据范围,所以还是记忆一下常见的数据的范围
数据类型 范围1 范围2
unsigned char、char 255 ~ 0 127 ~ -128
unsigned short、short 65525 ~ 0 32767 ~ -32768
unsigned int、int 4,294,967295 2147483647 ~ -2147483648

2.浮点数

1.浮点数的表示

1.浮点数的组成

QQ截图20221207201444

  • 浮点数V = (-1)^s * M * 2^E 表示, 由符号位、尾数、阶数
  • 符号数(sign):决定浮点数的正负
  • 尾数(significand): 就是图中frac,表示二级制小数
  • 阶数(exponent):就是2^E中的e,表示对浮点数加权值

对于浮点数有两种float、double,其对于三个组成部分的bit数为 flaot: s(1)、e(8) 、f(23) double:s(1)、e(11) 、f(52),double的精度大于float

对于浮点数主要由三种的表示方式:

QQ截图20221207202913

  • 规格化的,其中e不等于0也不等于255
  • 非规格化的,其中e 等于0
  • 特殊值,其中e 等于255

2.规格化的浮点数

  • 规格化的,其中e不等于0也不等于255

QQ截图20221207203111

对于规格化的浮点数就是表示正常的浮点数,其中两个点需要注意

  • E = e - bias,bias(等于2^(e的总位数 - 1) - 1),在float中其等于2^(8 - 1) - 1= 127,double中等于 2^(11 - 1) - 1 = 1023,在float类型中E_min = -126、E_max = 127, 若是在计算时超过这两个值中的一个则出现了溢出

  • 还有就是在计算尾数时,规格数省略了小数点前的1,也是说在计算时需要加上1

3.非规划的

  • 非规划的浮点数e = 0

QQ截图20221207204456

对于非规划的浮点数有两个用处,要注意的是非规划的浮点数的 阶数E = 1 - bias = -126是非常小的,还有就是 M = f是没有隐藏的1

  • 表示0,当M = f = 0,尾数的总和等于 0,阶数E = -126,又因为其有s符号位,所有就有+0.0 和 -0.0 两种0的表示方式
  • 表示非常接近0.0的数,因为阶数E = -126是非常小了 V = (-1)^s * M * (2)^(-126)将会是一个非常小的数,此时无论正负都接近于0.0

4.特殊值

  • 特殊值,其中e 等于255

QQ截图20221207204513

对于特殊值有两种作用:

  • 表示无穷值,此时不光e = 255, f = 0,根据符号位可以表示正负无穷
  • 当f 不等于0是,表示不是数(not a number),比如根号下-1,两个无穷相减

2.浮点数的加法

浮点数的加法有以下步骤:

  • 对阶、有效位数相加、将结果规格化、检查溢出、舍入(需要根据题目进行精度舍入)

下面将将会举一个例子:

QQ截图20221207210820

先将10进制数转化成二级制数

QQ截图20221207210128

然后进行对阶,即就是将低位的浮点数的阶数提高到于高位的浮点数相同,以便下一步操作

QQ截图20221207210136!](./%E5%9B%BE%E7%89%87/QQ%E6%88%AA%E5%9B%BE20221207210136.png)

然后将有效数进行相加

QQ截图20221207210147

将计算结果进行规格化同时判断阶数是否超过规定范围: -126 ~ 127,若是超过就是发生了溢出,等到的结果就不正确了

QQ截图20221207210153

最后根据题目要求进行精度的舍入,如果到达精度则不需要操作

3.浮点类型与其他类型

QQ截图20221207210206

在C语言中进行类型转换由于不同类型的表示方式不同,可能会出现我们不期望的结果,所以我们需要了解在相互转换的过程当中可能会出现哪些错误

  • int ——> float,数字不会溢出,但是可能会出现舍入问题 12345没有舍入问题(比它小的也一定没有)
  • int / float ——>,并不会出现问题
  • double ——> float,可能会溢出成无穷值 或者 出现舍入问题 如果是原来的数就是flaot再转为double再转回去就不会舍入
  • float / double,这个可能出现的问题就比较多了,比如:向0舍入、值溢出、……,其他情况需要具体分析

3.运算部件

1.二进制加法

QQ截图20221210145049

1.半加器与全加器

在二进制加法中,运算的主要部分包括两个运算位和进位,首先我们做出一个简单的加法器(只考虑两个运算位),即就是半加器

QQ截图20221210145100

  • 在半加器中,我们只考虑两个二进制的运算位,而不考虑进位,可以看出当两个数同一时我们才会产生进位,只要有一出现输出就是一,此时我们考虑将两个半加器组成一个全加器,就是把sum输出和进位当做两个运算位,在次进行运算即可,如下图

QQ截图20221210145109

此时我们得到了一个全加器,器其进位信号的表达式经过化简的得到 进位 = a * b + (a + b) * c_in,当我们将一个个的全加器串联起来就可以得到一个完整的加法器

2.行波加法器与先行加法器

1.行波加法器

  • 首先我们把一个全加器简化成下面的部件

QQ截图20221210145124

  • Cin表示低位的进位,a、b是两个运算位,S表示输出位,Cout表示进位,将32位的全加器串联起来就可以得到一个32的加法器,这个加法器也叫 32位行波加法器

QQ截图20221210145138

可以看出,从最低位开始每次两个数的对于位进行相加,同时加上低位是进位(0位没有低位进位,即是0),并将加法结果输出,进位传个高位,这里我们注意到一个点,只有在低位运算结束之后我们才会得到低位的进位,也就是说只有低位运算之后我们才可以进行高位的运算,这就产生了数据依赖,所以我们的这种串联的行波加法器效率并不高,所以也就有了下面的先行加法器的出现

2.先行加法器

  • 在上面行波加法器中,我们的关键路径就是需要等待低位传来的进位信号,所以我们想有没有办法提前得到低位传来的进位信号,对于进位信号的计算我们可以算出 C_2 = a * b + (a + b) * C_1,可以得到一个全加器的进位只与 低位的运算数和进位得到(最低位的进位已知),所以我们可以通过计算得到所以的进位,如下图

QQ截图20221210151821

  • 所以说就可以通过计算得到所以的进位,但是注意随着位数的增加,需要进行的计算也就增多,所以我们只考虑部分的全加器进行先行计算进位,然后再将其串联起来或者嵌套进行先行计算,如下图表示的

QQ截图20221210151849

这样相比行波加法器效率就会高很多,其实本质上就是提高了计算的并行性,使在同一时间内可以进行多个相同的运算

2.二进制减法器

  • 首先介绍一个组合逻辑电路,数据选择器(多路选择器),通常由2选1、4选1、8选1、16选1,在数电中74ls151就是u一个81数据选择器,下面展示一个41数据选择器,数据选择器会在减法器、TLB等中用到

QQ截图20221210151859

我们可能经常会听到可以使用加法来代替减法,也的确是这样的,在计算机中我们也是使用加法器来代替减法器,为什么可以呢? 在前面我们有 -x = ~x + 1,这个式子,这里简单说一下证明,x + ~x 始终会等于 FFF…… ,即是全1的二级制代码,而在补码中全1的二进制代表的就是-1,所以就有 x + ~x = -1,化简一下就得到了 -x = ~x + 1,所以一个数的减法就可以表示成 加上 ~x + 1,所以我们就可以得到对应的减法器了。

QQ截图20221210161321!](./%E5%9B%BE%E7%89%87/QQ%E6%88%AA%E5%9B%BE20221210161321.png)

此时,我们就的得到了减法器,但是还有一个问题就是如何让加法器 和 减法器 合并成一个器件,这是就要用到数据选择器,当前选择进行减法时,我们需要的数据是 ~x 和 最低位进位为1,选择加法时我们需要的是原数据 和 最低位进位为0,即我们就有了下面的加法、减法二合一的电路

QQ截图20221210162019

3.二级制乘法器

  • 在计算二级制乘法时,我们在前面学过对于一个数进行二进制乘法时,我们可以将其转化成对于进行左移和加法运算,如对于一个数x进行乘 9 可以转化成 x * 2^3 + x * 2^0 = (x << 3) + (x << 1), 此时就可以将二进制乘法转化成二级制加法和逻辑运算,对于一个二进制数的乘法步骤如下

QQ截图20221210162516

  • 可以看出,当进行二级制乘法时对于乘数我们只关心为1的情况,同时被乘数要随着乘数的右移进行左移,所以就有了下面的计算步骤

1.乘法计算步骤

QQ截图20221210162529

2.标准乘法器

QQ截图20221210162538

  • 对于进行的乘法的步骤,首先控制单元,判断乘数的最低位是否为1,当为1时,将被乘数的值通过ALU加到我们的乘积中(也就是结果当中),然后每次将乘数右移,被乘数左移,当乘数的最低位为1时再次进行上步骤
  • 控制单元的作用(重点):由图像我们可以看出,控制单元管理乘数寄存器的右移操作、被乘数寄存器的左移操作、以及ALU是否进行加法运算和是否对乘积进行写操作,具体作用看上图控制测试的连出先即可
  • 在进行进行计算时我们可以发现,在返回结果的时候我们只需要32位,而我们的乘积结果寄存器中却使用了64位,而对应的乘数每次进行右移,渐渐的高位的位置就不再被使用,对此我们进行优化,将乘积寄存器和和乘数寄存器合并

3.改进版乘法器

QQ截图20221210162553

  • 得到如图的优化版乘法器,当然除了这种优化还可以进行提高并行性的优化

4.快速乘法器

QQ截图20221210164812

  • 本质类似于加法器中的先行加法器,对于运算提高了并行性,所以提高运算的效率,当然除了上述的方法还有booth算法、华莱士树乘法器等

4.二进制除法

  • 在以往的408中并没有考到

对于二进制除法的运算如图

QQ截图20221210162616

对于除法运算,首先会将被除数放入余数寄存器当中,然后进行除法运算,若余数小于0则把商的低位赋为0然后商左移,除数右移,同时将余数寄存器的值恢复,进行下一轮运算;若余数大于等于,就将商最低位赋为1然后左移,除数右移,进行下一轮运算

QQ截图20221210162631

  • 注意:在上面的加、减、乘的运算中,都是会有其固定的时钟周期的,而除法就比价特殊其时钟周期是在一个范围内,根据具体的数据而定

对于除法器和其优化版本如图:

QQ截图20221210162638

QQ截图20221210162645

posted on   一七_2  阅读(71)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示