计组第二章:数据运算(C语言
第一节:数制与编码
补充内容:
机器数内,补码表示整数、移码表示阶码、原码表示浮点数尾数部分
需要进行位拓展的原因:
ALU的位数是固定的,运算前可能需要把短数据扩展为长数据
通用寄存器位数是固定的,把数据存入寄存器时,可能需要进行长度扩展
主存内的各种数据长度不一,有时需要把短数据扩展为长数据
进位计数法:
只需要记忆二进制、八进制、十六进制分别的前缀和后缀即可,容易遗忘和混淆
进制数转换:
二进制转为八进制、十六进制小数点左边高位补零,右边低位补零,解释均右向左翻译
例如0110.01010解释为八进制,06.24,解释为十六进制,6.50
十六进制、八进制的互相转换经由二进制完成互相转换
十进制转为十六进制、八进制首先转为二进制再考虑转为高位进制
十进制整数转为二进制直接考虑凑整法,速度远高于书上给定的计算方法
对于小数部分若位数少于五位内可以直接凑整,高于五位建议用乘基取余法得结果
高位进制(十进制)能覆盖所有低进制表达范围,低进制不一定能表达高进制
四大码以及相应计算:
高位、低位补零的数量具体以字长为定,低位、高位均是以零拓展不以其他拓展
提纲:(写一遍下列的转换过程是最迅速、最有效的回忆方法
1.真值转原码、反码、补码、移码;2.原码转真值、反码、补码、移码
3.反码转原码、真值、补码、移码;4.补码转真值、原码、反码、移码
5.移码转真值、原码、反码、移码;6.补码转其负值补码
稍微补充一句话:移码表示为真值的话,直接二进制解释整段机器码然后减去偏移量
参考篇目:码的互相转换以及补充
相应表示范围和特点:(根据下列图表进行一次回忆,这是最迅速有效的复习方法
书上需要注意的内容是各个码的特点和其应用场合、比较对比,容易被忽略
整数的表示:
无符号整数的取值范围大小和有符号整数的取值范围大小相同,无非范围不同
在计算机中尤其要注意有符号数的默认表示方式(有符号整数)均是以补码形式存储的
后面习题里面也有不少这样的坑存在
C语言类型转换:
整型数据类型需要记忆、背诵和默写,这是没办法的事情
有符号转为无符号、无符号转为有符号只改变了对内部存储的补码的解释方式而已
注意内部以补码方式存储,所以解释的时候就会有一些小细节存在
无符号数和有符号数的结合运算以无符号数为准,运算均是基于补码的(不论加减都是
强制转换长转短直接截断、短转长永远以最高位符号位去拓展,以补码方式解释
短向长拓展补充:
若原先被声明为无符号或者本身就是无符号(Unsigned short/int/long、char
那么拓展到长位不论长位是有符号还是无符号,一律采用零拓展
补充:C语言中,Unsigned p,是一个可行的定义,默认采用三十二位,int,可证明
习题总结分析:
1:对于十进制转二进制、八进制、十六进制,如果低于十位可以直接转,能够凑的
高于十位建议采用书上的除基取余的方法
4:反码、原码零的表示均不唯一,补码和移码均唯一,建议回顾上述内容即可反应出
5:补码转原码,正数补码和原码、反码一样,负数对应改变即可
6:一个比较重要的结论,记住即可,全部取反后加一即可得到其补码相反数
7:原码、反码能表示的数的量均是255个,因为有重复的零,其他均是256个不同的数
11:需要注意的是补码当表示负数的时候后面一越多越大,零越多越小,图表内容
13、14、17:人不会两次踏进同一条河流,但我真的会重复犯当时错过的问题
本质是因为这边是补码,而个人计算的时候一直用原码考虑,因而导致了犯错
按照图表即可迅速做出来结果
23:需要注意的是补码负数表示为:-1到-128,正数表示为0到127,所以会产生溢出
24:关于移码的计算,个人的建议是直接写出机器数后再减去偏移量,这样更加直观些
30、33:注意在计算机里面无符号、有符号整数均是以补码形式存储的,需要注意
在有符号情况下,需要特别注意解释的问题,无符号反正是原码直接解释就可以的了
第二节:运算方法和运算电路
基本数电知识:
运算器的基本构成和介绍
基本运算部件的介绍,运算器的基本构成、基本功能需要记忆,偏考察内容
带标志加法器
带标志加法器的基本原理需要了解,否则做题的时候困难会有些困难
主要看标志位的生成是如何实现的,这一块考察比较频繁(虽然理解功能即可
加减运算电路部分在统考曾经以小题考察过一次,需要知晓其运行流程
ALU及相关考点
此外一个较容易考察的是多路选择器、三态门、ALU的位数和功能间的关系
MUX(多路选择器:
ALU支持K种功能则需要logK个输入信号位,和多路选择的含义一样的
若是八个输入端则需要3位二进制来表达不同的输入端口号
本质用二进制表达端口号,控制信号即为指定该位置的输入可进入
三态门,区分于非门,当op为1时允许通过,当op为0时禁止信号通过
op只需要一位即可,因为一位就是二进制的0和1两种状态
带标志加法器的标志位:
PS:标志位本身是一定会被如实计算出来的
这就是书上注意中“运算器本身无法识别所处理的二进制串有符号与否”所表达的
不论是有符号还是无符号,这一些标志位全部都会计算出来,不管有没有意义
1.无符号数
关于进位、借位符CF、无符号数溢出判断:
这一块的内容具体建议看笔记(写在草稿上,和全加器的电路、加法原理可以结合
当加法的时候,输入端进位为零,两个无符号数相加若产生了最高位进位即为溢出
当减法时,输入端进位为一,减数运算中转为其补码形式,其符号位隐含在外
若两者相加的结果没有产生最高位进位,即隐含符号位是一个负号,自然表示溢出
因为无符号数不能表示负数
上述即为两种溢出情况,具体可随意列举例子辅助理解
ZF零标志:
每一位的本位和或非即可得到结果,若全为零即为零,无符号有符号均有意义
无符号全零表示为零,补码形式下全零也表示为零(均以补码解释,带符号与否罢
2.有符号数
SF最高位符号:
因为无符号数最高位就是零实际上表示没意义,所以SF只用于表示有符号数
OF溢出标识:
溢出判断的第三种方法常被用于加法电路中的溢出判断
有符号数溢出判断:
一般二进制数运算,只有负+负、正+正、负-正、正-负会溢出
在补码表示法中后面两者减法均会变为加法,转为前面两种情况
一位符号位判断:(也称模二补码
最终即为两个同符号数相加产生了不同符号数即为溢出
双符号位判断:(也称模四补码
或者采用双符号位,最高位记录先前的符号,次高位记录当前符号,如果不同即溢出
数值位进位、符号位进位判断:
实际上应该从原理角度理解,一个位的值由三者确定,两个本位、一个低位进位
可以列出具体的真值情况,当且仅当本位进位和低位进位相同的时候不可能产生溢出
其实本质依旧是两个相同符号位在运算后是否产生不同符号位的问题(草稿上有
记忆即可,电路原理很少具体考察
二进制运算:
移位运算:
分为算数移位、逻辑移位;一者基于无符号数、一者基于有符号数
算数移位分为:原码移位、补码移位、反码移位
逻辑移位:全部位都参与运算
算术移位:
原码左移,符号位不参与移位;原码右移,符号位不参与移位
补码左移,符号位参与移位;补码右移,符号位参与移位,正数添0负数添1
计算机中默认以补码类型存储整数,除非特别声明原码,不然都按补码方式进行移位
逻辑移位溢出即为高位进位为一,精度损失则为低位移除一个一
算数移位溢出即为左移前后符号位产生变化(注:符号位也参与运算,低位出一损精度
需要注意的是不论怎么移动一次性移动多位需要观察每一次移动后是否发生溢出
如果其中有一次产生了溢出,那么这个移动就是溢出的!!!!
二进制加法计算:
只需要训练加法运算、Y补转-Y补即可,只需要多练习几遍即可迅速反应
除法、乘法运算:
建议参考PPT,只需要掌握原码乘除法即可(何况即使是这两者统考也从来没有考察过
乘除法的电路逻辑,其符号位均是异或出来的结果,和运算结果溢出与否无关
乘法运算中只要有一次运算溢出就会直接中断,除法运算中有一次除零也会产生中断
在计算机中整数以补码的形式存储,所以除法中只有-2^31/-1会产生溢出,上溢
乘法电路的溢出判断,简单来说就是不该表示数值的位被用来表示数值,自然就是溢出
习题总结分析:
1:ALU是运算器的核心部件,ALU的核心部件又是加法器,ALU是算数逻辑单元
2:数据通路在计算单元、控制单元中都是必然存在的,同时还需要存在控制反馈通路
4:补码符号位参与移位,需要注意的是这题移位是溢出的
需要把移位看作是一次次分离的移动,而不能视作一次整体观察结果
中间但凡出现有一次移位溢出,那么就代表这次移位溢出
5:算数左移溢出,意味着有符号数最高位移动后符号产生了变化,无符号则是移出一
6:负数补码,最高位参与移位,右移一位,最高位补符号位即可
7:十六进制、八位进制数相加可以不考虑转为二进制,而直接在进制基础上运算
8:补码左移、右移符号位均参与移动,右移以符号位补充,左移低位补零
9:溢出判断电路必须依赖于异或门
移位电路一般依赖于多路选择器、移位寄存器、ALU实现,一般不用门电路(较复杂)
译码电路一般在存储器单元、控制器单元中(用于解析地址和操作码
编码电路很少见到,但一般会出现在中断向量的构成(中断信号编译为中断向量
10:注意“根本原因”,考察这种类型直接往最深的原因找,越偏硬件的描述越准确
11:此类类型题目,建议首先将补码转为原码再转为十进制值运算
因为十进制是一眼就能看出来在不在范围内的,而二进制就不一定了(接触时间短
12:存储时只需要一个符号位即可,模四补码仅在ALU运算单元(移位、四则)双符号
其他部件内模四补码只采用一位符号位(逻辑运算部件内)
20:不论逻辑左移还是算数左移的结果均是一样的,但逻辑右移和算数右移不同
21:输入端信息X和Y,Y要么全部取反,要么保持不变(减数)
依靠输入端的进位零或者一来调整是否是加减法,加法进位为零,减法进位为一
恰好可以把Y转为补码进行运算
在运算器内是不含符号位的,符号位是隐含在外的!!!因而进位与否决定是否溢出
减法不进位溢出,加法进位即溢出
不论无符号数还是有符号数,在计算机中均默认以补码解释!
22、24:Y的补码得到-Y的补码是全部取反后再加一,而不是除符号位取反后加一
25:INT、short类型均默认是有符号整数
按照原码转为补码的规则进行转换,先转为其对应的原码,再转为对应补码即可
不要和高位拓展相互混淆,这个并没有涉及到位数拓展,但确实可以联系起来考察
位拓展是位数不同的时候的拓展,这里仅仅是原码转补码,不要联系
26、28:最简易、迅速的方法就是直接计算其十进制数再反求其范围即可
27:乘二就相当于左移一位,除二相当于右移一位,具体用补码的移位法即可
31:需要注意下计算本身
低位进位自然是一,高位进位也是很明确的就是一,异或的结果就是零
对于有符号溢出的OF,依据电路原理,最高位进位为一,次高位进位同样也是一
自然也就完成实现这道题的计算,溢出判断尽可能按照电路的来,即两个进位的比较
除非是在自己做补码运算的时候,两个符号相同的才需要考虑溢出的事情
32:这里进行一个比较重要的补充,在计算机中,一切都是归于底层电路运算的
不论是有符号数还是无符号数,他们经过的电路加法部件都是一样的
所以完全可以直接化为补码二进制,然后进行电路内的运算,观察各自标志位的生成
类似于无符号溢出与否只需要异或低位进位和高位进位即可判断CF
有符号数溢出判断只需要异或最高位进位和次高位进位,这都是完全能统一的
直接进行运算即可,没有任何可以担心的事情,负数补码就直接全部取反然后加一即可
也可以看出是和计算机内取反进位为一的逻辑是完全一致的,按照电路逻辑判断即可
第三节:浮点数的运算
浮点数的表示和组成
浮点数的阶码位数决定了其表示范围,尾数位数决定了其精度范围,基数两者均决定
一般分析以float、double为主,需要各自记住阶码的长度
浮点数表示范围
浮点数的溢出判断取决于阶码而不取决于尾数,其中上溢需要异常中断处理
下溢可以继续参与运算,无非在运算中被当作为机器零
浮点数规格化
以二为基,左规一位尾数增大、阶码减少一位,右规一位尾数减少、阶码增大一位
规格化的目的是提高浮点数的表示精度,因为可以抛弃高位无效零而获得低位有效精度
以二为规格化数基数时,最高位必然为有效位,且可以隐藏增加精度(IEEE754
以四为基数时,最高两位不全为零,无法隐藏做有效位,因为只能确定至少一个一
一般尾数以原码、补码小数的方式表达,最高位(即小数点前一位为符号位
比较容易错的是非IEEE754类型的浮点数表示
例如阶码可能用的是补码、原码表示,甚至可能带符号
后面的尾数同样也可能用原码、补码表示,同时符号位可能不带可能带,以及隐藏位
这些都是具体题目中的坑,如果感觉不太行,建议回书上把错题做一遍即可
IEE754
IEE754的浮点数隐藏了最高位有效位,因而其写作具体值的时候需要刻意多加有效位
关于回忆内容:
单、双浮点数的阶码长度;阶码偏移量与最大最小值;表示范围(正负数)
阶码全零、阶码全一的特殊表示含义;阶码全一时的最大值、阶码全零的非规格最小值
实数与IEEE754的互相转换(尤其注意实数转IEEE754中的幂为负的情况,反之亦然
对阶本身不可能产生溢出,只可能产生精度误差
关于舍入的判断(何时需要舍入、舍入的方法、舍入的结果可能是:相等、不变、变大
关于溢出的判断,何时可能会发生溢出?(规格化和尾数舍入、计算结束舍入时
数据大小端、对齐存储
首先需要明确,Char:8位、Short:16位、Int:32位、float:32位、Double:64位
Long类型具体看计算机字长多少位来决定位数(潜在考点)
关于存储本身,一般按字节存储,也就是八位一个存储单元编一个地址
大端就是按顺序存储、小端就是逆着存储,注意对一般的二进制而言,其左边是高位
边界对齐,只需要记住:结构体内各个变量需要按照取余对齐
结构体本身需要按照最大成员变量值取模对齐来最终断定该结构体的大小
个人认为较为重要的反而是关于存储、流水线这一块的叙述,和后面的内容能有关联
尤其需要注意这一段内容的最后一句话:精简计算机指令结构采用边界对齐
因为每条指令的取指令时间都是一样的,所以才能适应流水线,这个需要清楚
此外,补充一句:这是用空间换时间,在存储中填充浪费不少存储单元
习题总结分析:
2、3:阶码的长度决定了能表示的范围大小、尾数的长度决定了能表示的精度
基数本身既能决定表达的范围大小,也能决定表示的精度高低
相对于定点数而言,浮点数能表示的范围更大,但精度更低,这是一个必然的现象
5:一般题目内写出的尾数,都是补码、原码小数,其最高位就是符号位
至于IEEE754,需要清楚的是其符号位在一开始就声明了,所以后面就是个真值
隐藏位补上后就是类似于1.XXXXX的形式,最高位的一应该要被解释为一个数
而一般的浮点数并没有默认是IEEE754标准的,也就是其符号位一般配合在小数点前
具体符号位取几位就要看情况了,变形补码就是取两位符号位
6:个人认为需要区分一般的非规格化浮点数和IEEE754标准下的非规格化浮点数
一般的非规格化浮点数只需要去考虑尾数是否完成规格化即可了
而IEEE754因为尾数默认都是完成规格化的,所以才需要去关注阶码本身
混淆了一般的浮点数与IEEE754,或者说把浮点数认为就只有那么一种IEEE754标准的
7:浮点数对阶只可能是小向大靠拢,大向小会损失最高位导致严重误差/溢出
因而对阶不存在左规的情况,对阶只能是右规,且对阶本身是不可能导致溢出的情况的
左规尾数增大、阶码减小,右规尾数减小、阶码增大
10:需要刻意回忆的内容:浮点数表示的最小、最大值分别是多少、阶码全零全一含义
12:注意审题,和当初错法一模一样,这里说的是从大到小的顺序
至于移码,一般默认的移动位数是整体表示位数的一半,最高位是一代表必然是正数
例如八位二进制其移动的位数就是128//127
13:简单来说是产生了混淆,采用隐藏位的目的是提高浮点数的精度我是清楚的
但实际上我对规格化的目的是不够清晰的,能有什么结果也是不清晰的
反而是因为IEEE754默认规定了均为规格化浮点数导致误以为隐藏位和规格化含义一致
实际上个人是根本不理解规格化的目的,就以为其是方便计算,这个是这样的逻辑
规格化最主要的目的就是提高精度,把无效的高位零都给规格化掉,使得尾数可表更多
15:关于溢出,何时可能产生溢出?这里特指上溢
浮点数相加、相减后的尾数舍入可能会导致溢出;浮点数右规可能会溢出
下溢本身是不重要,无关紧要的,阶码全零即产生了下溢,一般直接视作机器数零
而上溢是需要调用系统中断的,这一点有明显的不同,浮点数的溢出主要看阶码
18:阐述一个为什么开始对阶对了半天没对准的原因:这边的阶码居然给了九位…
19:阶码全零、阶码全一分别对应的几种情况是需要分别记忆的
此外还需要特别注意阶码为零的情况下的非规格化浮点数,其乘的指数是2^-126
阶码全一的情况下其阶码乘的指数是2^127,而不是全一、全零时所对应的移码值
阶码所规定的范围就是固定的,不会有例外的指数值,这一点需要记住
21:错法是一样的,认为浮点数只有IEEE754标准,从而多算了一位隐藏位
23、24:只需要考虑浮点数的尾数即可,非IEEE754标准都只需要看尾数
只有IEEE754标准因为天然就完成了规格化,所以需要刻意去留意阶码的情况
25:浮点数舍入只有对阶、右规格化、计算后的舍入三种情况
至于定点数的计算,其实其主要在于不可能出现超过表达位数以外的位数参与运算
不同长度的数据类型会在高位拓展,而不会在低位拓展,永远是低位互相对齐运算的
自然其运算范围只在其能表达的范围内,自然就不会有舍入这个概念在,自然错
浮点数的问题就在于其最低位不一定会对齐,而计算过程中超过表达范围的又会保留
自然就会导致舍入的问题,舍入本身不一定会产生误差,可能就是不变
27:
28:小端存储是顺序相反的、大端存储是顺序正的,这里就是把顺序给搞反了
此外需要特别注意下存储单元的存放方式,其是一个位置一个存储单元,不是间隔一个
在量不大的情况下建议一个个列清楚再做题目,否则可能会算多一个或少一个位置
30:应该是题目的问题,Unsigned本身实际上不能代表任意的长度,必须要加类型的
不论是Unsigned//Signed,他们归根结底只是一个解释方式而已,不能算作是一个类型
虽然题目想要考察的就是按边界对齐和不按边界对齐的知识点罢了
31:大端存储按顺序,后面的>>符号含义为向右移动一位,向左也是可以的
32:
33:
35:
41:其实按理来说,浮点数加减运算是没有左规的,虽然其表述确实是对的…
可能还是过分严谨了点,统考好像就是这样的,太严谨就没必要了
42:和上面说的错法是一样的,当时应该就特意注意过这种问题,必须要一个个列出来
因为存储单元序号=0,这个位置实际上也是存储了一个存储单元的数据的
45:基本又是犯了类似的错误,计算上面多半是出错了一些,此外需要注意一点
这里虽然类型长16位或者32位,但是其本身如果按字节编址只占2个或者4个存储单元
中间计算存储位置的时候切记不要把32/16代入运算…
48:严重错误,个人在对阶的时候根本没有考虑阶码的正负!!!!!于是就错了!
阶码本身是带正负的,把尾数增大那么阶码就需要变小,这是左规!!阶码算出是负的
所以问题就是在于移码算错(甚至先前计算的时候移码正的也算错…
问题更多在于C语言中的类型转换,未来会进行一定程度的补充