1
0
mirror of https://github.com/Didnelpsun/CS408.git synced 2026-06-16 15:07:38 +08:00

更新进程管理与操作数

This commit is contained in:
Didnelpsun
2021-08-19 23:57:14 +08:00
parent a1a0b210ab
commit 94409ced81
9 changed files with 399 additions and 261 deletions

View File

@@ -1,8 +1,8 @@
// 初始化最大长度
#define MAXSIZE 5
// 定义默认值
#define DEFAULTELEM '0'
#define DEFAULTDATA '0'
// 定义最大值
#define INFINITY 32767
//#define INFINITY 32767
// 定义默认数据类型
typedef char element_type;

View File

@@ -3,159 +3,162 @@
#include "head.h"
// 单链表结点
typedef struct LinkListNode {
class LinkListNode {
public:
// 数据
element_type data;
struct LinkListNode* next;
} LinkListNode, *LinkList;
// 指针
LinkListNode* next;
// 构造函数
LinkListNode();
explicit LinkListNode(element_type data);
};
// 由于C语言无法参数赋值所以必须借助一个中间变量完成
// 初始化有头节点单链表
int InitLinkListWithHead(LinkList &list) {
list = (LinkListNode*)malloc(sizeof(LinkListNode));
if (list) {
list->data = NULL;
list->next = nullptr;
return 0;
}
else {
printf("InitLinkListWithHead:分配空间失败!");
return 1;
}
class LinkList{
public:
// 指针
LinkListNode* next;
// 链表长度
int length;
// 构造函数
LinkList();
// 判空
bool Empty();
};
class LinkListWithHead: public LinkList{
public:
// 构造函数
LinkListWithHead();
};
class LinkListWithoutHead: public LinkList{
public:
// 数据
element_type data;
// 构造函数
LinkListWithoutHead();
};
LinkListNode::LinkListNode() {
this->data = NULL;
this->next = nullptr;
}
// 初始化无头节点单链表
int InitLinkListWithoutHead(LinkList &list) {
list = nullptr;
return 0;
LinkListNode::LinkListNode(element_type data) {
this->data = data;
this->next = nullptr;
}
// 创建有头节点单链表
LinkList CreateLinkListWithHead() {
auto list = (LinkListNode*)malloc(sizeof(LinkListNode));
if (list) {
list->data = NULL;
list->next = nullptr;
}
else {
printf("CreateLinkListWithHead:分配空间失败!");
}
return list;
LinkList::LinkList() {
this->next= nullptr;
this->length =0;
}
// 创建无头节点单链表
LinkList CreateLinkListWithoutHead() {
return nullptr;
LinkListWithHead::LinkListWithHead() = default;
LinkListWithoutHead::LinkListWithoutHead() {
this->data = NULL;
}
bool LinkList::Empty() {
if(this->length==0){
return true;
} else {
return false;
}
}
// 判断有头节点单链表是否为空
int EmptyLinkListWithHead(LinkList list) {
if (list->next) {
return 0;
}
else {
return 1;
}
}
// 判断无头节点单链表是否为空
int EmptyLinkListWithoutHead(LinkList list) {
if (list) {
return 0;
}
else {
return 1;
}
}
// 插入有头节点单链表元素
// 0号节点是头节点
int InsertLinkListWithHead(LinkList list, int index, element_type elem) {
if (index < 1) {
printf("InsertLinkListWithHead:插入索引值过小!\n");
return 1;
}
// 定义一个结点指针p指向当前扫描到的结点
LinkListNode* p;
// 定义一个变量i表示当前扫描到的结点的索引号
int i = 0;
// 将链表头结点指向p为第0个结点
p = list;
// 循环遍历到达指定索引号的单链表的结点
// 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
while (p->next != NULL && i < index - 1) {
p = p->next;
i++;
}
// 如果此时i小于index-1表示遍历完还没有到达对应的索引
if (i < index - 1) {
printf("InsertLinkListWithHead:插入索引值过大!\n");
return 1;
}
// 此时i==index-1
LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
if (s) {
s->data = elem;
// 将p原来的后继给新的结点
s->next = p->next;
p->next = s;
return 0;
}
else {
printf("InsertLinkListWithHead:分配内存失败!\n");
return 1;
}
}
// 插入无头节点单链表元素
// C语言也无法调用这个函数
int InsertLinkListWithoutHead(LinkList list, int index, element_type elem) {
if (index < 0) {
printf("InsertLinkListWithoutHead:插入索引值过小!\n");
return 1;
}
if (index == 0) {
LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
if (s) {
s->data = elem;
// 将s的后继设为list指针
s->next = list;
// 将list指针设置为s指针
list = s;
return 0;
}
else {
printf("InsertLinkListWithoutHead:分配内存失败!\n");
return 1;
}
}
// 定义一个结点指针p指向当前扫描到的结点
LinkListNode* p;
// 定义一个变量i表示当前扫描到的结点的索引号
int i = 0;
// 将链表头结点指向p为第0个结点
p = list;
// 循环遍历到达指定索引号的单链表的结点
// 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
while (p->next != NULL && i < index - 1) {
p = p->next;
i++;
}
// 如果此时i小于index-1表示遍历完还没有到达对应的索引
if (i < index - 1) {
printf("InsertLinkListWithoutHead:插入索引值过大!\n");
return 1;
}
// 此时i==index-1
LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
if (s) {
s->data = elem;
// 将p原来的后继给新的结点
s->next = p->next;
p->next = s;
return 0;
}
else {
printf("InsertLinkListWithoutHead:分配空间失败!\n");
}
}
//// 插入有头节点单链表元素
//// 0号节点是头节点
//int InsertLinkListWithHead(LinkList list, int index, element_type elem) {
// if (index < 1) {
// printf("InsertLinkListWithHead:插入索引值过小!\n");
// return 1;
// }
// // 定义一个结点指针p指向当前扫描到的结点
// LinkListNode* p;
// // 定义一个变量i表示当前扫描到的结点的索引号
// int i = 0;
// // 将链表头结点指向p为第0个结点
// p = list;
// // 循环遍历到达指定索引号的单链表的结点
// // 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
// while (p->next != NULL && i < index - 1) {
// p = p->next;
// i++;
// }
// // 如果此时i小于index-1表示遍历完还没有到达对应的索引
// if (i < index - 1) {
// printf("InsertLinkListWithHead:插入索引值过大!\n");
// return 1;
// }
// // 此时i==index-1
// LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
// if (s) {
// s->data = elem;
// // 将p原来的后继给新的结点
// s->next = p->next;
// p->next = s;
// return 0;
// }
// else {
// printf("InsertLinkListWithHead:分配内存失败!\n");
// return 1;
// }
//}
//
//// 插入无头节点单链表元素
//// C语言也无法调用这个函数
//int InsertLinkListWithoutHead(LinkList list, int index, element_type elem) {
// if (index < 0) {
// printf("InsertLinkListWithoutHead:插入索引值过小!\n");
// return 1;
// }
// if (index == 0) {
// LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
// if (s) {
// s->data = elem;
// // 将s的后继设为list指针
// s->next = list;
// // 将list指针设置为s指针
// list = s;
// return 0;
// }
// else {
// printf("InsertLinkListWithoutHead:分配内存失败!\n");
// return 1;
// }
// }
// // 定义一个结点指针p指向当前扫描到的结点
// LinkListNode* p;
// // 定义一个变量i表示当前扫描到的结点的索引号
// int i = 0;
// // 将链表头结点指向p为第0个结点
// p = list;
// // 循环遍历到达指定索引号的单链表的结点
// // 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
// while (p->next != NULL && i < index - 1) {
// p = p->next;
// i++;
// }
// // 如果此时i小于index-1表示遍历完还没有到达对应的索引
// if (i < index - 1) {
// printf("InsertLinkListWithoutHead:插入索引值过大!\n");
// return 1;
// }
// // 此时i==index-1
// LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
// if (s) {
// s->data = elem;
// // 将p原来的后继给新的结点
// s->next = p->next;
// p->next = s;
// return 0;
// }
// else {
// printf("InsertLinkListWithoutHead:分配空间失败!\n");
// return 1;
// }
//}

View File

@@ -1,15 +1,19 @@
#include <cstdio>
#include <cstdlib>
#include <cstdlib>
#include <iostream>
#include "head.h"
#pragma warning(disable:6385)
#pragma warning(disable:6386)
using namespace std;
// 顺序表
class SequenceList {
public:
element_type *data{};
int length{};
// 构造函数
SequenceList();
// 插入函数
virtual bool Insert(int index, element_type elem);
// 打印函数
@@ -33,8 +37,6 @@ public:
// 静态顺序表
class StaticSequenceList: public SequenceList{
public:
element_type data[MAXSIZE]{};
int length;
// 构造函数
StaticSequenceList();
// 插入函数
@@ -44,9 +46,6 @@ public:
// 动态顺序表
class DynamicSequenceList: public SequenceList{
public:
// 给一个指针来分配动态数组
element_type *data;
int length;
// 已分配的最大容量
int max_size;
// 构造函数
@@ -61,14 +60,17 @@ private:
bool ReIncrease(int len);
};
SequenceList::SequenceList() {
this->length = 0;
}
StaticSequenceList::StaticSequenceList() : SequenceList() {
this->length=0;
this->data = (element_type*)malloc(MAXSIZE * sizeof(element_type));
}
DynamicSequenceList::DynamicSequenceList() : SequenceList() {
// 初初始化动态顺序表长度为0
this->max_size=0;
this->length = 0;
// 申请一片连续的存储空间
auto* space = (element_type*)malloc(MAXSIZE * sizeof(element_type));
if (space) {
@@ -76,19 +78,19 @@ DynamicSequenceList::DynamicSequenceList() : SequenceList() {
this->max_size = MAXSIZE;
}
else {
printf("InitSequenceList:分配空间失败!\n");
cout << "InitSequenceList:分配空间失败!" << endl;
}
}
void SequenceList::Printf() {
for (int i = 0; i < this->length; i++) {
printf("第%d个元素值为%c\n", i + 1, this->data[i]);
cout << "" << i + 1 << "个元素值为" << this->data[i] << endl;
}
}
bool DynamicSequenceList::OtherIncrease(int len) {
if (len <= 0) {
printf("OtherIncrease:申请空间应该大于0\n");
cout << "OtherIncrease:申请空间应该大于0" << endl;
return false;
}
// 申请一片连续的存储空间
@@ -106,14 +108,14 @@ bool DynamicSequenceList::OtherIncrease(int len) {
return true;
}
else {
printf("OtherIncrease:重新分配空间失败!\n");
cout << "OtherIncrease:重新分配空间失败!" << endl;
return false;
}
}
bool DynamicSequenceList::ReIncrease(int len) {
if (len <= 0) {
printf("ReIncrease:申请空间应该大于0\n");
cout << "ReIncrease:申请空间应该大于0" << endl;
return false;
}
// 申请一片连续的存储空间
@@ -127,7 +129,7 @@ bool DynamicSequenceList::ReIncrease(int len) {
else {
this->max_size = 0;
this->length = 0;
printf("ReIncrease:分配其他地址空间失败!\n");
cout << "ReIncrease:分配其他地址空间失败!" << endl;
return false;
}
}
@@ -139,12 +141,12 @@ bool SequenceList::Insert(int index, element_type elem) {
bool StaticSequenceList::Insert(int index, element_type elem) {
// 当静态顺序表已经满了就不能插入任何元素
if (this->length >= MAXSIZE) {
printf("Insert:静态顺序表空间不足,插入失败!\n");
cout << "Insert:静态顺序表空间不足,插入失败!" << endl;
return false;
}
// 索引位置从0开始所以可以插入的范围是0到list->length
if (index > this->length || index < 0) {
printf("Insert:插入索引%d超过索引范围\n", index);
cout << "Insert:插入索引" << index << "超过索引范围!" << endl;
return false;
}
// 从最后一个元素开始交换后移list->length是空的
@@ -158,7 +160,7 @@ bool StaticSequenceList::Insert(int index, element_type elem) {
bool DynamicSequenceList::Insert(int index, element_type elem) {
if (index > this->length || index < 0) {
printf("Insert:插入索引%d超过索引范围\n", index);
cout << "Insert:插入索引" << index << "超过索引范围!" << endl;
return false;
}
// 当动态顺序表已经满了,需要新增一个位置
@@ -166,7 +168,7 @@ bool DynamicSequenceList::Insert(int index, element_type elem) {
if (this->length >= MAXSIZE) {
bool result = this->ReIncrease(1);
if (!result) {
printf("Insert:申请空间失败!\n");
cout << "Insert:申请空间失败!" << endl;
return false;
}
}
@@ -182,7 +184,7 @@ bool SequenceList::LoopInsert(element_type *elem, int start, int end) {
for (int i = 0; i < end; i++) {
bool result = this->Insert(i, elem[i + start]);
if (!result) {
printf("LoopInsert:循环插入失败!\n");
cout << "LoopInsert:循环插入失败!" << endl;
return false;
}
}
@@ -191,7 +193,7 @@ bool SequenceList::LoopInsert(element_type *elem, int start, int end) {
bool SequenceList::Delete(int index, element_type &elem) {
if (index >= this->length || index < 0) {
printf("Delete:删除索引超过索引范围!\n");
cout << "Delete:删除索引" << index << "超过索引范围!" << endl;
return false;
}
elem = this->data[index];
@@ -204,7 +206,7 @@ bool SequenceList::Delete(int index, element_type &elem) {
bool SequenceList::MultiDelete(int index, int len, element_type *elem) {
if (index + len >= this->length || index < 0) {
printf("MultiDelete:删除索引超过索引范围!\n");
cout << "MultiDelete:删除索引" << index << "超过索引范围!" << endl;
return false;
}
for (int i = index; i < this->length - len; i++) {
@@ -219,8 +221,8 @@ bool SequenceList::MultiDelete(int index, int len, element_type *elem) {
element_type SequenceList::GetElem(int index) {
if (index >= this->length || index < 0) {
printf("GetElem:查找索引超过索引范围!\n");
return DEFAULTELEM;
cout << "GetElem:查找索引" << index << "超过索引范围!" << endl;
return DEFAULTDATA;
}
return this->data[index];
}
@@ -232,7 +234,7 @@ int SequenceList::Locate(element_type elem) {
return i;
}
}
printf("Locate:未能定位到对应值的元素!\n");
cout << "Locate:未能定位到对应值的元素!" << endl;
return -1;
}
@@ -249,7 +251,6 @@ bool SequenceList::Destroy() {
if (this->data) {
free(this->data);
}
delete this;
return true;
}

View File

@@ -3,7 +3,7 @@
int main()
{
SequenceListTest();
// LinkListTest();
//SequenceListTest();
LinkListTest();
return 0;
}

View File

@@ -8,11 +8,10 @@ int SequenceListTest() {
list.Insert(0, 'a');
element_type a[6] = {'1','2','3','4','5','6'};
list.LoopInsert(a, 0, 6);
printf("%c", list.data[2]);
/*element_type b[3] = { '9', 'a', 'e' };
list.LoopInsert(b, 1, 2);*/
list.Printf();
//printf("%c", list.data[2]);
element_type b[3] = { '9', 'a', 'e' };
list.LoopInsert(b, 1, 2);
list.Printf();
/*list.Printf();
printf("\n");
int len = 2;
@@ -26,21 +25,16 @@ int SequenceListTest() {
InitDynamicSequenceList(&dlist);
OtherIncreaseDynamicSequenceList(&dlist, 15);
printf("%d", dlist.max_size);*/
//int index = list.Locate('5');
//printf("%d", index);
//list.Destroy();
int index = list.Locate('5');
index = list.GetElem(1);
cout << list.Empty() << endl;
list.Destroy();
return 0;
}
int LinkListTest() {
LinkList list = nullptr;
InitLinkListWithoutHead(list);
// InitLinkListWithHead(list);
//LinkList list = CreateLinkListWithHead();
// int empty = EmptyLinkListWithHead(list);
// LinkList list = CreateLinkListWithoutHead();
int empty = EmptyLinkListWithoutHead(list);
printf("%d", empty);
LinkList list;
cout << list.Empty() << endl;
return 0;
}

View File

@@ -59,3 +59,106 @@ $C.$既可按地址寻址又可按内容寻址
$D.$以上说法均不完善
解:$C$。相联存储器既可以按地址寻址又可以按内容(通常是某些字段)寻址,为与传统存储器区别,又称按内容寻址的存储器。
**例题** 在$CPU$的寄存器中,()对用户是完全透明的。
$A.$程序计数器
$B.$指令寄存器
$C.$状态寄存器
$D.$通用寄存器
解:$B$。汇编程序员可以通过指定待执行指令的地址来设置$PC$的值,状态寄存器、通用寄存器只有为汇编程序员可见,才能实现编程,所以不是完全透明的。而$IR$、$MAR$、$MDR$是$CPU$的内部工作寄存器,对程序员均不可见。
## 计算机性能指标
**例题** 存储字长是指()。
$A.$存放在一个存储单元中的二进制代码组合
$B.$存放在一个存储单元中的二进制代码位数
$C.$存储单元的个数
$D.$机器指令的位数
解:$B$。存储体由许多存储单元组成,每个存储单元又包含若干存储元件,每个存储元件能寄存一位二进制代码“$0$”或“$1$”。可见,一个存储单元可存储一串二进制代码,称这串二进制代码为一个存储字,称这串二进制代码的位数为存储字长。
**例题** 下列关于机器字长、指令字长和存储字长的说法中,正确的是()。
.三者在数值上总是相等的
Ⅱ.三者在数值上可能不等
Ⅲ.存储字长是存放在一个存储单元中的二进制代码位数
Ⅳ.数据字长就是$MDR$的位数
$A.$Ⅰ、Ⅲ
$B.$Ⅰ、Ⅳ
$C.$Ⅱ、Ⅲ
$D.$Ⅱ、Ⅳ
解:$C$。机器字长、指令字长和存储字长,三者在数值上可以相等也可以不等,视不同机器而定。一个存储单元中的二进制代码的位数称为存储字长。存储字长等于$MDR$的位数,而数据字长是数据总线一次能并行传送信息的位数,它可以不等于$MDR$的位数。
**例题** $CPU$的$CPI$与下列()因素无关。
$A.$时钟频率
$B.$系统结构
$C.$指令集
$D.$计算机组织
解:$A$。$CPI$是执行一条指令所需的时钟周期数,系统结构、指令集、计算机组织都会影响$CPI$,而时钟频率并不会影响$CPI$,但可加快指令的执行速度。
**例题** 下列关于“兼容”的叙述,正确的是()。
$A.$指计算机软件与硬件之间的通用性,通常在同一系列不同型号的计算机间存在
$B.$指计算机软件或硬件的通用性,即它们在任何计算机间可以通用
$C.$指计算机软件或硬件的通用性,通常在同一系列不同型号的计算机间通用
$D.$指软件在不同系列计算机中可以通用,而硬件不能通用
解:$C$。兼容指计算机软件或硬件的通用性,因此选项$A$、$D$错。选项$B$中,它们在任何计算机间可以通用,错误。选项$C$中,兼容通常在同一系列的不同型号计算机间,正确。
**例题** 某台计算机只有$Load/Store$指令能对存储器进行读/写操作,其他指令只对寄存器进行操作。根据程序跟踪试验结果,已知每条指令所占的比例及$CPI$数如下表所示。
指令类型|指令所占比例|CPI|指令类型|指令所占比例|CPI
:------:|:----------:|:-:|:------:|:----------:|:-:
算术逻辑指令|43%|1|Store指令|12%|2
Load指令|21%|2|转移指令|24%|2
假设程序由$M$条指令组成。算术逻辑运算中$25\%$的指令的两个操作数中的一个已在寄存器中,另一个必须在算术逻辑指令执行前用$Load$指令从存储器中取到寄存器中。因此有人建议增加另一种算术逻辑指令,其特点是一个操作数取自寄存器,另一个操作数取自存储器,即寄存器-存储器类型,假设这种指令的$CPI$等于$2$。同时,转移指令的$CPI$变为$3$。求新指令系统的平均$CPI$。
解:首先我们必须明白这里是做了什么。
首先原来的算术逻辑运算是对数据进行算术逻辑操作,数据都是从寄存器中获取,所以需要$Load$指令将数据从存储器中取到寄存器中,所以每操作一个算术逻辑,都需要$Load$两个数据。
而现在发现有一个数据已经在寄存器中了,所以只用取一个数据到寄存器就可以了。所以就定义这个只用取一个操作数的指令为一个新的算术逻辑指令,$CPI=2$,又算术逻辑运算中$25\%$的指令是这种指令,所以算术逻辑指令拆出了$0.25\times0.43M$条指令。
因为新指令包含了$Load$操作,所以$Load$指令也需要拆出$0.25\times0.43M$条指令。
这样就拆出两个合成了一个$0.25\times0.43M$条新指令,即原来是逻辑运算和$Load$各$1+2$,现在是逻辑运算、新逻辑运算和$Load$各$1+1+1$,多余的$0.25\times0.43M$条取数操作就被简略了。
所以新指令总数为$M+(0.25\times0.43M)-(0.25\times0.43M)-(0.25\times0.43M)=0.8925M$。
其他指令数量不变,需要更新$CPI$和对应的占比:
指令类型|指令所占比例|CPI
:------:|:----------:|:--:
算术逻辑指令|(0.43M-0.43M×0.25)/0.8925M=0.3613|1
算术逻辑指令(新)|(0.43M×0.25)/0.8925M=0.1204|2
Load指令|(0.21M-0.43M×0.25)/0.8925M=0.1148|2
Store指令|0.12M/0.8925M=0.1348|2
转移指令|0.24M/0.8925M=0.2689|3
所以新$CPI'=1\times0.3613+2\times0.1204+2\times0.1148+2\times0.1348+3\times0.2689=1.9076$。

View File

@@ -241,20 +241,24 @@ int main(){
### 中央处理器
+ $CPU$主频:$CPU$内数字脉冲信号振荡的频率。单位为赫兹。
+ $CPU$时钟周期:$CPU$主频(时钟主频)=$1\div CPU$时钟周期。单位为纳秒或微秒。
+ $CPU$时钟周期:$CPU$主频(时钟主频)=$1\div CPU$时钟周期。一个时钟多少秒。单位为纳秒或微秒。
+ $CPI$$Clock\,cycle\,Per\,Instruction$):执行一条指令所需的时钟周期数。
+ 执行一条指令的耗时= $CPI\times CPU$时钟周期。
+ $CPU$执行时间(整个程序的耗时)=$CPU$时钟周期数÷主频=(指令条数×$CPI$)÷主频。
+ $IPS$$Instructions\,Per\,Second$):每秒执行多少条指令,$IPS$=主频÷平均$CPI$。也可以得到$MIPS$即每秒执行多少百万条指令。
+ $FLOPS$$Floating-point\,Operations\,Per\,Second$):每秒执行多少次浮点运算
**例题** 某$CPU$主频为10000Hz某程序包含100条指令平均来看指令任CPI=3该程序在该$CPU$上执行需要多久?
100×3÷1000=0.3s。
+ $IPS$$Instructions\,Per\,Second$):每秒执行多少条指令,$IPS$=主频÷平均$CPI$。也可以得到$MIPS$即每秒执行多少百万条指令。由于每个机器有不同指令集,所以使用此进行性能比较有缺陷。
+ 指令周期:一条指令需要多少秒,为$1/IPS$
+ $FLOPS$$Floating-point\,Operations\,Per\,Second$):每秒执行多少次浮点运算。因此有$MFLOPS$、$GFLOPS$、$TFLOPS$、$EFLOPS$、$ZFLOPS$分别代表每秒$10^6$、$10^9$、$10^{12}$、$10^{15}$、$10^{18}$、$10^{21}$次浮点运算
### 系统整体
+ 数据通路带宽:数据总线一次所能并行传送信息的位数(各硬件部件通过数据总线传输数据)。
+ 吞吐量:指系统在单位时间内处理请求的数量。它取决于信息能多快地输入内存,$CPU$能多快地取指令,数据能多快地从内存取出或存入,以及所得结果能多快地从内存送给一台外部设备。这些步骤中的每一步都关系到主存,因此,系统吞吐量主要取决于主存的存取周期。
+ 响应时间:指从用户向计算机发送一个请求,到系统对该请求做出响应并获得它所需要的结果的等待时间。通常包括$CPU$时间(运行一个程序所花费的时间)与等待时间(用于磁盘访问、存储器访问、$I/O$操作、操作系统开销等时间)。
+ 基准程序是用来测量算机处理速度的一种实用程序,以便于被测量的计算机性能可以与运行相向程序的其它计算机性能进行比较。
+ 基准程序是用来测量算机处理速度的一种实用程序,以便于被测量的计算机性能可以与运行相向程序的其它计算机性能进行比较。但是也存在缺陷,因为基准程序的性能可能与某一段代码密切相关从而对此进行特别优化。
### 专业术语
+ 系列机。具有基本相同的体系结构,使用相同基本指令系统的多个不同型号的计算机组成的一个产品系列。
+ 兼容。指计算机软件或硬件的通用性,即使用或运行在某个型号的计算机系统中的硬件/软件也能应用于另一个型号的计算机系统时,称这两台计算机在硬件或软件上存在兼容性。
+ 软件可移植性。指把使用在某个系列计算机中的软件直接或进行很少的修改就能运行在另一个系列计算机中的可能性。
+ 固件。将程序固定在$ROM$中组成的部件称为固件。固件是一种具有软件特性的硬件,固件的性能指标介于硬件与软件之间,吸收了软/硬件各自的优点,其执行速度快于软件,灵活性优于硬件,是软/硬件结合的产物。例如,目前操作系统已实现了部分固化(把软件永恒地存储于只读存储器中)。

View File

@@ -0,0 +1,35 @@
# 数据表示与运算习题
## 数制与编码
### 进位计数制
#### 十进制转换为R进制
**例题** 将十进制的$75.3$转换为二进制并保留三位。
首先将$75$拿出来,以基数$2$相除:
$75\div2=37\dots1$$37\div2=18\dots1$$18\div2=9\dots0$$9\div2=4\dots1$$4\div2=2\dots0$$2\div2=1\dots0$$1\div2=0\dots1$,这个顺序是从低位到高位的,所以$75$转换二进制就是$1001011$。
然后是对小数$0.3$的处理:
$0.3\times2=0.6=0+0.6$$0.6\times2=1.2=1+0.2$$0.2\times2=0.4=0+0.4$,这个顺序是从高位到低位的,所以$0.3$转换二进制就是$0.010$。
所以转换最后得到$1001011.010B$。
### 数据校验
**例题**
#### 循环冗余校验码
**例题** 在$CRC$中,接收端检测出某一位数据错误后,纠正的方法是()。
$A.$请求重发
$B.$删除数据
$C.$通过余数值自行纠正
$D.$以上均可

View File

@@ -15,21 +15,21 @@
#### R进制
+ 基数每个数码位所用到的不同符号的个数r进制的基数r
+ 基数每个数码位所用到的不同符号的个数r进制的基数$r$
+ R进制转换为十进制$K_nK_{n-1}\cdots K_2K_1K_0K_{-1}K_{-2}\cdots K_{-m}=K_n\times r^n+K_{n-1}\times r^{n-1}\cdots K_2\times r^2+K_1\times r^1+K_0\times r^0+K_{-1}\times r^{-1}+K_{-2}\times r^{-2}\cdots K_{-m}\times r^{-m}=\sum_{i=-m}^nK_i\times r^i$。
+ 二进制:0、1
+ 二进制:$0$、$1$
+ 使用二进制的原因:
1. 可使用两个稳定状态的物理器件表示。
2. 01正好对应逻辑值假、真。方便实现逻辑运算。
2. $0$$1$正好对应逻辑值假、真。方便实现逻辑运算。
3. 可很方便地使用逻辑门电路实现算术运算。
+ 八进制:0、1、2、3、4、5、6、7。可以用下标方式表明,也可以用结束的O或开头的0表示。如$(1643)_8$、016431643O。
+ 十进制:0、1、2、3、4、5、6、7、8、9。可以用下标方式表明,也可以用结束的D表示,如$(1643)_{10}$、1643D。
+ 十六进制:0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F。可以用下标方式表明,也可以用结束的H或开头的0x表示。如$(1643)_{16}$、0x16431643H。
+ 八进制:$0\sim7$。可以用下标方式表明,也可以用结束的$O$或开头的$0$表示。如$(1643)_8$、$01643$、$1643O$
+ 十进制:$0\sim9$。可以用下标方式表明,也可以用结束的$D$表示,如$(1643)_{10}$、$1643D$
+ 十六进制:$0\sim9$、$A$、$B$、$C$、$D$、$E$、$F$。可以用下标方式表明,也可以用结束的$H$或开头的$0x$表示。如$(1643)_{16}$、$0x1643$、$1643H$
#### 二进制与八进制或十六进制转换
+ 二进制转换八进制:三位一组,每组转换成对应的八进制符号,整数部分不全则最高位用0填充,小数部分不全则最低位用0填充。
+ 二进制转换十六进制:四位一组,每组转换成对应的十六进制符号,整数部分不全则最高位用0填充,小数部分不全则最低位用0填充。
+ 二进制转换八进制:三位一组,每组转换成对应的八进制符号,整数部分不全则最高位用$0$填充,小数部分不全则最低位用$0$填充。
+ 二进制转换十六进制:四位一组,每组转换成对应的十六进制符号,整数部分不全则最高位用$0$填充,小数部分不全则最低位用$0$填充。
+ 八进制转换二进制:每位八进制对应的三位二进制。
+ 十六进制转换二进制:每位十六进制对应的四位二进制。
@@ -56,7 +56,7 @@
+ 整数部分需要使用除基取余法,小数部分需要使用乘基取整法。
+ 对于十进制数,需要把它分为整数部分和小数部分两个部分进行处理。
+ 已知R进制转换为十进制的方法:$K=K_nK_{n-1}\cdots K_2K_1K_0K_{-1}K_{-2}\cdots K_{-m}=K_n\times r^n+K_{n-1}\times r^{n-1}\cdots K_2\times r^2+K_1\times r^1+K_0\times r^0+K_{-1}\times r^{-1}+K_{-2}\times r^{-2}\cdots K_{-m}\times r^{-m}$。
+ 已知$R$进制转换为十进制的方法:$K=K_nK_{n-1}\cdots K_2K_1K_0K_{-1}K_{-2}\cdots K_{-m}=K_n\times r^n+K_{n-1}\times r^{n-1}\cdots K_2\times r^2+K_1\times r^1+K_0\times r^0+K_{-1}\times r^{-1}+K_{-2}\times r^{-2}\cdots K_{-m}\times r^{-m}$。
+ 分为整数部分和小数部分:$K=N+F$。
+ 首先把整数拿出来得到$N=K_n\times r^n+K_{n-1}\times r^{n-1}\cdots K_2\times r^2+K_1\times r^1+K_0\times r^0$。
+ 对这个数除以基数$r$,得到$X=K_n\times r^{n-1}+K_{n-1}\times r^{n-2}\cdots K_2\times r^1+K_1\times r^0$,这时候就会得到一个余数$K_0$。所以$N=rX+K_0$,这时候就能算出$K_0$这个位数了。
@@ -69,57 +69,51 @@
+ 将整数和小数合在一起就是最后的结果。
+ 有时候小数会出现无法彻底转换的情况,需要考虑保留多少位。
**例题** 将十进制的75.3转换为二进制并保留三位。
首先将75拿出来以基数2相除
75÷2=37……137÷2=18……118÷2=9……09÷2=4……14÷2=2……02÷2=1……01÷2=0……1这个顺序是从低位到高位的所以75转换二进制就是1001011。
然后是对小数0.3的处理:
0.3×2=0.6=0+0.60.6×2=1.2=1+0.20.2×2=0.4=0+0.4这个顺序是从高位到低位的所以0.3转换二进制就是0.01。
所以转换最后得到1001011.01。
同理也可以使用拼凑法将数字拼凑成对应的数值。这种方法对于只有整数的数值比较好用。
$2^{12}$|$2^{11}$|$2^{10}$|$2^{9}$|$2^{8}$|$2^{7}$|$2^{6}$|$2^{5}$|$2^{4}$|$2^{3}$|$2^{2}$|$2^{1}$|$2^{0}$|$2^{-1}$|$2^{-2}$|$2^{-3}$
:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:
4096|2048|1024|512|256|128|64|32|16|8|4|2|1|0.5|0.25|0.125
### 真值与机器数
使用正负号表示正负数的就是真值。
将数的符号和数值一起来编码的,如原码、反码、补码就是机器数。
### BCD码
即Binary-Coded Decimal用二进制编码的十进制。
$Binary-Coded\,Decimal$,用二进制编码的十进制。
使用4bit来表示0到9这十个数而4bit能表示十六个数所以会冗余六个组合。
使用$4bit$来表示$0$到$9$这十个数,而$4bit$能表示十六个数,所以会冗余六个组合。
#### 8421码
8421码是一种有权码1、2、3、4位分别对应8、4、2、1,使用常规的二进制来表示十进制:
$8421$码是一种有权码,第$1$、$2$、$3$、$4$位分别对应$8$、$4$、$2$、$1$,使用常规的二进制来表示十进制,冗余最后六个
0|1|2|3|4|5|6|7|8|9
:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
0000|0001|0010|0011|0100|0101|0110|0111|1000|1001
如9858421码表示就是1001 1000 0101。
$985$用$8421$码表示就是$1001\,1000\,0101$
使用8421码表示的数字进行算术运算的方式是先按照二进制的方式进行运算若最后结果不在映射表中即落在没有定义的10101111中就直接加上6(因为有六位无效,所以加上六位跳过无效的位数)从而进一位,多了一段补全0。每个段对应的数值合在一起就是原来的结果。
使用$8421$码表示的数字进行算术运算的方式是先按照二进制的方式进行运算,若最后结果不在映射表中,即落在没有定义的$1010$到$1111$中,就直接加上$6$(因为有六位无效,所以加上六位跳过无效的位数)从而进一位,多了一段补全$0$。每个段对应的数值合在一起就是原来的结果。
如5+8=0101+1000=1101=13不在映射表中则对1101加6即计算19得到1 0011这个值补齐得到0001 0011而按照8421码最高位的0001不再代表权值16而代表十位的1,而后面是3从而组合在一起就代表了13。
$5+8=0101+1000=1101=13$,不在映射表中,则对$1101$加$6$,即计算$19$,得到$1\,0011$这个值,补齐得到$0001\,0011$,而按照$8421$码,最高位的$0001$不再代表权值$16$,而代表十位的$1$,而后面是$3$,从而组合在一起就代表了$13$
#### 余三码
在8421码的基础上全部加上三
$8421$码的基础上全部加上三:
0|1|2|3|4|5|6|7|8|9
:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
0011|0100|0101|0110|0111|1000|1001|1010|1011|1100
余三码因为加上了三,所以每一位的权值映射关系就破坏了,所以这是一种无权码,不能分别对应8、4、2、1的值。
余三码因为加上了三,所以每一位的权值映射关系就破坏了,所以这是一种无权码,不能分别对应$8$、$4$、$2$、$1$的值。
#### 2421码
与8421码一样都是一种有权码但是映射的方式不同1、2、3、4位分别对应2、4、2、1
$8421$码一样都是一种有权码,但是映射的方式不同,第$1$、$2$、$3$、$4$位分别对应$2$、$4$、$2$、$1$
0|1|2|3|4|5|6|7|8|9
:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
@@ -129,26 +123,29 @@ $2^{12}$|$2^{11}$|$2^{10}$|$2^{9}$|$2^{8}$|$2^{7}$|$2^{6}$|$2^{5}$|$2^{4}$|$2^{3
#### 英文字符表示
ASCII码数字英文符号一共128个字符使用7位就可以表示128个字符但是通常会高位补0凑足1B
$ASCII$码,数字英文符号一共$128$个字符,使用$7$位就可以表示$128$个字符,但是通常会高位补$0$凑足$1B$
+ 其中32126是可印刷字符其他都是控制或通信字符。
+ 数字480011 0000到570011 1001后面4位就是数字的8421码。
+ 大写字母650100 0001到900101 1010前面三位是010后面五位代表1到26。
+ 小写字母970110 0001到1220111 1010前面三位是011后面五位代表1到26。
+ 其中$32$到$126$是可印刷字符,其他都是控制或通信字符。
+ 数字:$48$$0011\,0000$)到$57$$0011\,1001$),后面$4$位就是数字的$8421$码。
+ 大写字母:$65$$0100\,0001$)到$90$$0101\,1010$),前面三位是$010$,后面五位代表$1$到$26$
+ 小写字母:$97$$0110\,0001$)到$122$$0111\,1010$),前面三位是$011$,后面五位代表$1$到$26$
#### 中文字符表示
+ GB 2312-801980年推出汉字加符号共7445个表示的字符。中文有两个字节。
+ 区位码94个区每个区94位
+ 国标码为了中文字符表示与英文字符表示共存防止GB编码被认为是ASCII码的0到32位的控制或通信字符所以在94区94位的基础上还要各自加上32即20H防止信息交换时冲突
+ 汉字内码国标码只能用于信息传输而如果是存储在计算机上由于前128位已经被ASCII码占用了所以在国标码的基础上再各自加80H128从而计算机识别字符时看到0到128之间的就能辨认出是ASCII码大于128的就是GB码。因为ASCII码高位是0而GB码是两个字节且高位都是1
+ 输入编码:如拼音、五笔等供人类输入,输入编码输入后转换为国标码再转成汉字内码存储
+ 汉字字形码:把汉字输出成汉字的样子
+ $GB\,2312-80$$1980$年推出汉字加符号共$7445$个表示的字符。中文有两个字节。
+ 汉字编码包括汉字的输入编码、汉字内码、汉字字形码,用于输入、内部处理、输出
+ 输入编码:如拼音、五笔等供人类输入,输入编码输入后转换为国标码再转成汉字内码存储
+ 区位码:两个字节表示一个汉字,每字节用七位码,将汉字和符号排成$94$个区,每个区$94$位。四位十进制数,前两位是区码,后两位为位码
+ 国标码:将十进制的区位码转换为十六进制。为了中文字符表示与英文字符表示共存,防止$GB$编码被认为是$ASCII$码的$0$到$32$位的控制或通信字符,所以在$94$区$94$位的基础上还要各自加上$32$,即$20H$,防止信息交换时冲突。国标码两字节最高位都是$0$
+ 汉字内码:国标码只能用于信息传输,而如果是存储在计算机上,由于前$128$位已经被$ASCII$码占用了,所以在国标码的基础上再各自加$80H$$128$),从而计算机识别字符时,看到$0$到$128$之间的就能辨认出是$ASCII$码,大于$128$的就是$GB$码。因为$ASCII$码高位是$0$,而$GB$码是两个字节且高位都是$1$
+ 国标码=区位码$H$+$2020H$。
+ 汉字内码=国标码$H$+$8080H$。
+ 汉字字形码:把汉字输出成汉字的样子。
#### 字符串
+ 若一个计算机按字节编址则每个地址对应Q1B。
+ 很多语言中将'\0'即00H作为字符串结束标志。
+ 若一个计算机按字节编址,则每个地址对应$Q1B$
+ 很多语言中将$'\backslash0'$即$00H$作为字符串结束标志。
+ 大端模式:将数据的最高有效字节存放在低地址单元中。
+ 小端模式:将数据的最高有效字节存放在高地址单元中
@@ -160,25 +157,25 @@ ASCII码数字英文符号一共128个字符使用7位就可以表示128
+ 码字:由若干位代码组成的一个字。
+ 两个码字间的距离:将两个码字逐位进行对比,具有不同的位的个数。
+ 码距:一种编码方案可能有若干个合法码字,各合法码字间的最小距离。
+ 当码距=1时无检错能力当码距=2时有检错能力当码距≥3时,若设计合理,可能具有检错、纠错能力。
+ 当码距$=1$时,无检错能力;当码距$=2$时,有检错能力;当码距$\geqslant3$时,若设计合理,可能具有检错、纠错能力。
#### 奇偶校验码
+ 奇校验码:整个校验码(有效信息位和校验位)中为1的个数为奇数。
+ 偶校验码:整个校验码(有效信息位和校验位)中为1的个数为偶数。
+ 奇校验码:整个校验码(有效信息位和校验位)中为$1$的个数为奇数。
+ 偶校验码:整个校验码(有效信息位和校验位)中为$1$的个数为偶数。
+ 偶位数出错时无法校验。
+ 对原始数据进行异或(模2加)运算,得到的结果即为校验位。
+ 对所有数据进行异或运算,结果为0表示未出错,为1代表出错。
+ 码距为2,只能检错,不能纠错。
+ 对原始数据进行异或(模加)运算,得到的结果即为校验位。
+ 对所有数据进行异或运算,结果为$0$表示未出错,为$1$代表出错。
+ 码距为$2$,只能检错,不能纠错。
#### 海明码
+ 将信息分组进行偶校验,从而得到多个校验位,从而能携带多种状态信息。
+ 设信息位为$n$,校验位为$k$,从而能表达$2^k$中状态,而信息位+校验位一共$n+k$位,只错一位的状态种数加上一种正确状态为$n+k+1$,从而$2^k\geqslant n+k+1$。
+ 令信息位为$D_i$,校验位为$P_j$,总海明码为$H_k$,其中校验位$P_j$必须放在海明码$H_k$位号位$2^{j-1}$的位置上,即1、2、4、8等。
+ 如果没有发生错误,则每一位进行检错都是0,若出现1,则说明出错。
+ 令信息位为$D_i$,校验位为$P_j$,总海明码为$H_k$,其中校验位$P_j$必须放在海明码$H_k$位号位$2^{j-1}$的位置上,即$1$、$2$、$4$、$8$等。
+ 如果没有发生错误,则每一位进行检错都是$0$,若出现$1$,则说明出错。
+ 为了检测是一位错还是两位错,一般会加上一个全校验位,对整体进行偶校验。
+ 具有一位和两位的纠错检错能力,三位以上则不能错。
+ 具有一位的纠错和两位的检错能力,三位以上则不能错。
n|1|2-4|5-11|12-26|27-57|58-120
:-:|:-:|:-:|:-:|:-:|:--:|:----:
@@ -186,22 +183,23 @@ k|2|3|4|5|6|7
#### 循环冗余校验码
+ 即CRC码其思想是
1. 数据发送、接受方约定一个“除数”。
2. K个信息位+R个校验位作为“被除数”,添加校验位后需保证除法的余数为0
3. 收到数据后,进行除法检查余数是否为0
+ 得到CRC码的方法
1. 确定K和R以及生成多项式对应的二进制码。其中R位生成多项式的最高次幂数。
2. 将信息码左移R位低位补0
+ 即$CRC$码,其思想是:
1. 数据发送、接受方约定一个“除数”生成多项式$G(x)$。$R$为$G(x)$位数减一
2. $K$个信息位+$R$个校验位作为“被除数”,添加校验位后需保证除法的余数为$0$
3. 收到数据后,进行除法检查余数是否为$0$
+ 得到$CRC$码的方法:
1. 确定$K$和$R$以及生成多项式对应的二进制码。其中R位生成多项式的最高次幂数。
2. 将信息码左移R位低位补$0$
3. 使用模二除法。
4. 余数就是校验位,只比多项式少一位。
5. 对全部数据进行多项式除,余数为0代表无措。
6. 若余数不为0,则出错。
7. 若$n$个信息位,$k$个校验位,若生成多项式得当,且$2^k\geqslant n+k+1$则CRC码可纠正一位错。实际上基本上不怎么用来纠错。
5. 对全部数据进行多项式除,余数为$0$代表无措。
6. 若余数不为$0$,则出错。
7. 若$n$个信息位,$k$个校验位,若生成多项式得当,且$2^k\geqslant n+k+1$,则$CRC$码可纠正一位错。实际上基本上不怎么用来纠错。
+ 检错:将收到的$CRC$码用生成多项式$G(x)$做模二出发,若除数为$0$则码字无误,若只有一位为$1$,则该位出错,更多位则无法检错。即只具有一位的检错纠错能力。
## 定点数
指小数点的位置不变使用常规计数法如96.94。
指小数点的位置不变,使用常规计数法,如$96.94$
### 定点数表示