在简略学习了第六章和第七章的内容后,我对计算机的程序设计层有了新的了解,这两章分别从低级程序设计语言与伪代码以及问题求解与算法设计两个方面对程序设计层进行了阐述,下面是我的收获与问题。
*** 第六章低级程序设计语言与伪代码***
6.1 计算机操作
计算机:计算机是能够存储,检索和处理数据的可编程电子设备。可编程的,存储,检索和处理是这个定义中的操作字。
存储,检索和处理是计算机能够对数据执行的动作。
控制单元执行的指令能够把数据存储到机器的内存中,在计器内存中检索数据,在算数逻辑单元中以某种方式处理数据。
6.2 机器语言
机器语言:由计算机直接使用的二进制编码指令构成的语言。【也是每种机器有的一个特定的能够被执行的操作集合】
Pep/8:一台虚拟机
虚拟机:为了模拟真实机器的重要特征而设计的假想机器。
Pep/8所反映的重要特性
程序计数器(PC):其中包括下一条即将被执行的指令的地址
指令寄存器(IR):其中包含正在被执行的指令的一个副本
累加器(是一个用来保存操作数据和结果的寄存器)
一个字节能够表示的最大十进制数是255,用二进制表示是111111,用十六进制表示是FF。一个字(16位)能够表示的最大十进制数是65535,用二进制表示是1111111111111用十六进制表示是FFFF。如果既要表示正数,又要表示负数,那么在量级上就会少一位(因为有一位用于表示符号),因此可以表示的十六进制值数的范围约为-7FFF到+7FFF,相当于十进制数的-32767到+32767。 当我们使用Pep/8虚拟机时,这一信息是十分重要的。
可用的比特数决定了我们可以使用的内存大小。
用地址指代内存中的某一特定字节
指令格式
指令先进入指令寄存器,然后译解,最后被执行。
一条指令有两个部分组成:8位的指令说明符和16位的操作数说明符
指令说明符(指令的第一个字节)说明了要执行什么操作和如何解释操作数的位置
操作数说明符(指令的第二和第三个字节)存放的是操作数本身或者操作数的地址。(注:有些指令没有操作数说明符)
在Pep/8中,操作代码(称为操作码)的长度从4比特到8比特不等(在此所讨论的操作码为4-5比特,4比特的第五位用来指定寄存器)
三比特的寻址模式说明符表示了解析指令中的操作部分,有两个类型。
立即寻址:寻址地址是000,指令的操作数说明符中存储的就是操作数;直接寻址:寻址地址是001,操作数说明符中存储的是操作数所在的内存地址名称。立即寻址模式和直接寻址模式的差别决定了操作中数据存储或将要被存储的位置
一元指令:没有操作数(要处理的数据),一元指令的长度是一个字节
以下是一些示例指令;
0000:终止程序
11100:将操作数载入寄存器A中
当一个地址用来指定一个字(而不是一个单独的字节)时,这一字的最左边的一字节就是给定的地址
1110:将寄存器A的内容存储到操作数中
0111:将操作数加到寄存器A中
浅灰色是数据,深灰色是地址
1000:减去操作数
01001:把字符输入操作数(这一指令只能使用直接寻址,所以输入的字符被存储在操作数说明符中显示的地址中)
01010:从操作数输出字符
6.3 一个程序实例
6.3.2 Pep/8模拟程序
装入程序:软件用于读取机器语言并把它载入内存的部分
从程序输入到执行所必需的步骤;安装Pep/8后单击图标启动程序,在窗口中输入之前的程序,点击装入程序,此时你的程序被加载到pep/8内存中,确保终端I/O按钮被选中的,单击执行按钮。执行程序,HELLO将出现在输出窗口。
6.4 汇编语言
汇编语言:一种低级语言,用助记码表示特定计算机的机器语言指令。
汇编器:把汇编语言程序翻译成机器代码的程序
6.4.2 汇编器指令
在机器语言程序中,每条指令都要先存储到内存中,然后才能执行
汇编器指令:翻译程序使用的指令
6.4.3 Hello程序的汇编语言版本
注释:为程序读者提供的解释性文字
汇编语言程序(输入)汇编器(输出)机器代码程序
6.4.5 具有分支的程序
negMsg:如果寄存器A是负数,那么PC的内容将被BRLT后面的操作数代替,使下一条指令从操作数指定的内存单元开始
finish:当显示出错误消息后,必须跳转到程序结束的STOP行
6.4.6 具有循环的程序
计数器:位于内存的一个为0的存储单元
6.5 表达算法
算法:解决方案的计划或概要,或解决问题的逻辑步骤顺序
伪代码:一种表达算法的语言
6.5.1 伪代码的功能
1.变量 2.赋值 3.输入/输出 4.选择 5.重复
-输入输出
双引号之间的字符叫做字符串,它告诉人们要输入什么,输出什么
-选择
用选择结构可以选择执行或跳过某项操作,还可以在两项操作中进行选择
选择结构使用括号中的条件决定执行哪项操作
使用缩进对语句进行分组,控制将返回到没有缩进的语句
符号“//"用于加注释,它并不是算法的一部分
-重复
布尔表达式:评价为真或假的表达式
伪代码语句;
变量:表示存储值或从中提取值的指定位置
赋值:把值存入变量
输入:读入一个值
输出:可能在屏幕上显示一个变量或一个字符串的内容
重复:只要条件满足,就重复执行一条或多条语句
if-then 选择:如果条件满足,就执行缩进语句;如果条件不满足,就跳过缩进语句
if-then-else 选择 :如果条件满足,就执行缩进语句,如果条件不满足,则执行Else之后的缩进语句
伪代码最终必须被翻译成可在计算机上运行的程序。一个伪代码语句可以被翻译成多种汇编语言语句,但是只能被翻译成一种高级语言语句
6.5.2执行伪代码运算
DIV是一个操作符,返回的是十进制的商;REM也是一个操作符,返回的是十进制的余数
6.5.3 写伪代码算法
桌面检查:在纸上走查整个设计
6.5.4 翻译伪代码算法
6.6测试
代码覆盖(明箱)测试法:通过执行代码中的所有语句测试程序或子程序的测试方法
数据覆盖(暗箱)测试法:把代码作为一个暗箱,基于所有可能的输入数据测试程序或子程序的测试方法
测试计划实现:用测试计划中规定的测试用例验证程序是否输出了预期的结果
问题;前面的指令格式与示范指令处的操作数说明符不知道怎么读出相应信息
第七章 问题求解与算法设计
7.1 如何解决问题
1945年,G.Polya写的名为《How to solve It:A New Aspect of Mathematical>>描述了经典的数学问题求解过程,若将文字‘未知量’换成‘问题’,把‘数据’换成‘信息’,把‘定理’换成‘解决方案’,那这个列表就适用于各种问题。下面是列表建议的几点策略;
7.1.1 提出问题
-1.理解问题
-2.找到信息和解决方案之间的联系。如果找不到直接的联系,则可能需要考虑辅助问题。最终应该得到解决方案
-3.执行方案
-4.分析得到的解决方案
7.1.2 寻找熟悉的情况
7.1.3 分治法
把大的问题分割成能够独立解决的小问题
7.1.4 算法
算法:在有限的时间内用有限的数据解决问题或子问题的明确指令集合
7.1.5 计算机问题求解过程
-1.分析和说明阶段
-2.算法开发阶段
-3.实现阶段
-4.维护阶段
7.1.6 方法总结【四个步骤】
-1.分析问题
-2.列出主要任务
-3.编写其余的模块
-4.根据需要进行组装和改写
7.1.7 测试算法
越早发现和修正问题,解决问题越容易,代价越小
7.2有简单参数的算法
简单(原子)变量是那些不能被分开的变量
7.2.1 带有选择的算法
顶级【主要】模块只是表达任务
任何一个分支都包含一连串的语句
7.2.2 带有循环的算法
一,记数控制循环
记数控制循环可以指定过程重复的次数,这个循环的机制是简单记录过程重复的次数并且在重复再次开始前检测循环是否已经结束
循环控制变量:这类循环有三个不同的部分,使用一个特殊的变量
-1.初始化:循环控制变量初始化为某个初始值
-2.测试:循环控制变量是否已经达到特定的值
-3.增量:循环控制变量以1递增
while循环被称为前测试循环,如果最初条件为假,则不进入循环
二,事件控制循环
循环中重复的次数是由循环体自身内发生的事件控制的循环被称为事件控制循环
当使用while语句来实现事件控制循环时,这一过程仍分为三个部分:事件必须初始化,事件必须被测试,事件必须被更新
嵌套结构:控制结构嵌入另一个控制结构的结构,又称为嵌套逻辑
三,示例求数字的平方根
初始猜测值与原始猜测值
抽象步骤:细节仍未明确的算法步骤
具体步骤:细节完全明确的算法步骤
7.3 复杂变量
如果我们还使用引用中的一串字母代表写入的一条信息。引用中的字母叫作字符串。
7.3.1 数组
数组是同构项目的有名集合,可以通过单个项目在集合中的位置访问它们。
项目在集合中的位置叫做索引。
在数组名后加上中括号并且括号中写上integer来保存整数值
搜索:搜索数组中的项,一次寻找一个特定的值。
排序:按顺序将元素放入数组,如果项是字符或字符串,将以字母顺序排列。
处理:处理是一种捕捉语言,包含了对数组中的项所做的所有其他计算。
7.3.2 记录
记录是异构项目的有名集合,可以通过名字单独访问其中的项目。
所谓异构,就是指集合中的元素可以不必相同,集合可以包括整数,实数,字符串或其他类型的数据。
记录可以把与一个对象相关的各种项目绑定在一起。
7.4 搜索算法
7.4.1 顺序搜索
布尔操作符包括特殊操作符AND,OR和NOT。
7.4.2 有序数组中的顺序搜索
7.4.3 二分检索
二分检索采用的是分治法,从中间开始。
二分检索算法假设要检索的数组是有序的,其中每次比较操作可以找到要找的项目或把数组减少一半。
二分检索:在有序列表中查找项目的操作,通过比较操作排除大部分检索范围
7.5 排序
7.5.1 选择排序
互换算法还可以需要有被互换的两个项目的索引
7.5.2 冒泡排序
冒泡排序法也是一种选择的排序,只是在查找最小值是采用了不同的方法。
比较排序算法的方法通常是看它们对数组排序的迭代次数,而冒泡排序要对数组中除最后一个元素以外的所有元素进行一次迭代
7.5.3 插入排序
选择排序的每次迭代之后,一个元素被放置到它的永久位置。而插入排序的每次迭代之后,一个元素将被放在相对于其他元素来说适当的位置。
7.6 递归算法
递归算法:当在一个算法中使用它自己时,这样的算法被称为递归算法。
递归:算法调用它本身的能力
每个递归算法至少有两种情况:基本情况和一般情况
基本情况:答案已知的情况
一般情况:调用自身来解决问题的更小版本的解决方案
所有递归解决方案的第一步都是确定尺寸系数。如果问题涉及的是数值,尺寸系数可能就是数值本身。如果问题涉及结构,那么尺寸系数可能就是结构的尺寸
7.6.1 子程序语句
调用单元:命名代码出现的地方
子程序有两种形式,一种是只执行特定任务的命名代码,一种是不仅执行任务,还返回给调用单元一个值(值返回子程序)。
第一种形式的子程序在调用单元中用作语句,第二种则用作表达式,返回的值被用来评估表达式。
7.6.2 递归阶乘
每次给出的数据称为参数
无限递归:子程序将不断地调用自身,直到运行时间支持系统耗尽了内存为止。
7.6.3 递归二分检索
递归算法必须从非递归算法中调用。
7.6.4 快速排序
先找一个分裂值,然后分两部分,直到不能分为止
如果问题陈述逻辑上分为两种情况(基本情况,一般情况),则递归是一种可行的选择。
7.7 几个重要思想
7.7.1 信息隐蔽
信息隐蔽:隐蔽模块的细节以控制对这些细节的访问的做法。(进行高级设计时不能见到低层的细节)
7.7.2 抽象
抽象:(隐藏细节后的结果)复杂系统的一种模型,只包括对观察者来说必须的细节。
数据抽象:把数据的逻辑视图和它的实现分离开
过程抽象:把动作的逻辑视图和它的实现分离开
控制抽象:把控制结构的逻辑视图和它的实现分离开
控制结构:用于改变正常的顺序控制流的语句
7.7.3 事物命名
标识符:在编写算法时,我们使用速记短语表示要处理的任务和信息,也就是说给数据和过程一个名字
将任务名设为短语,最终会被转化为单独的标示符。
转换过程:1.在算法中命名数据和动作 2.把这些名字转换成符合计算机语言规则的标识符。
7.7.4 测试
白盒测试:基于代码本身
黑盒测试:基于测试所有可能的输入值