第六章:低级程序设计语言与伪代码
6.1计算机操作
- 存储、检索、处理是计算机能够对数据进行执行的动作。
- 也就是说控制单元执行的指令能够把数据存储到机器的内存中,在机器内存中检索数据,在算数逻辑单元中以某种方式处理数据。
6.2机器语言
- 机器语言(machine language):由计算机直接使用的二进制编码指令构成的语言。
- pep/8:一台虚拟机
- 每一种计算机有一个特定的能够被执行的操作集合,称为这种计算机的机器语言。
虚拟机:为了模拟真实机器的重要特征而设计的假象机器。
- 指令格式
首先,我们需要研究pep/8的指令格式
一条指令由两个部分组成,即8位的指令说明符和(可选的)16位的操作数说明符
指令说明符说明了要执行什么操作和如何解释操作数的位置。操作数说明符(指令存放的第二个和第三个字节)存放的是操作数本身或者是操作数的地址。有些指令没有操作说明符。
其中指令的指令说明符部分,前四位为操作码,第五位为寄存器说明符或操作码的第五位后三位为寻址模式
寻址模式分为
立即寻址(000):指令的操作说明符中存储的是就是操作数
直接寻址(001):指令的操作说明符中存储的是操作数所在的内存地址名称
没有操作数的指令称为一元指令,这些指令没有操作说明符,一元指令符的长度是一字节
0000:停止执行
1100:将操作数载入寄存器A中
1110:将寄存器A中的内容存储到操作数中
0111:将操作数加到寄存器A中
1000:将寄存器A中的值中减去操作数的值
01001:把字符输入操作数
01010:从操作数输出字符
6.3一个程序实例
简而言之,所需要的就是将给出的二进制指令,转化为16进制,即构成了两种进制命令语言
6.3.1手工模拟
1)从程序计数器指定的位置读取下一条指令
2)译解指令(并且更新程序计数器)
3)如果需要,获取数据操作数
4)执行命令
第一步先将0000载入程序计数器,执行命令后,然后在PC上加三(因为一共有三个字节)
最后指令为00000000为一元指令周期停止
6.3.2pep8模拟程序
- 一个虚拟程序,用于我们理解程序,指令,代码格式样式
6.4汇编语言
- 一种帮助程序员的工具
- 汇编语言给每一条机器语言指令分配了一个助记编码,可以用这些助记码来代替二进制数字
汇编语言(assembly language):一种低级语言,用助记码表示特定计算机的机器语言指令
汇编器(assembler):把汇编语言程序翻译成机器代码的程序
6.4.1Pep/8汇编语言
由助记忆码,操作数,寻址模式说明符,指令的含义组成,具体细节在书中P112查阅
6.4.2汇编器指令
在机器语言程序中,每条指令都要先存到内存中,然后才能执行。从汇编语言开始,大多数程序设计语言都有两种类型的指令,即要翻译的指令和翻译程序使用的指令(理解有问题)
在书中为我们列出了汇编器中的几条有用的汇编器指令,这些汇编器指令也叫伪操作
汇编器指令也叫伪操作
汇编器指令也叫伪操作
汇编器指令(assembler directive):翻译程序使用的指令
6.4.3hello程序的汇编语言版本
Pep8汇编语言允许我们直接指定字符输出,还允许我们在指令旁边添加注释,注释是说明性文字,无论什么编程,注释都是重要的组成部分,编译器会忽略从分号开始到一行结束的所有字符,这就是一个注释
6.4.4编写一个新程序
在程序的设计中,先将数据放在程序的前面可以让数据的提取变得方便(0001开始读取)随后输入程序,这样就不需要先去考虑程序的字节
在每一次操作中,要先将值,字节块准备好并将需要的数据在指定的位置中读取,然后再去使用有关细节再P114~115看
6.4.6具有循环的程序
这是一个难点,我现在还不清楚英文排列出程序的含义
6.5表达算法
算法(alogrithm):解决方案的计划或概要,或解决问题的逻辑步骤顺序,
伪代码(pseudocode):一种表达算法的语言
6.5.1伪代码的功能
更像是是人们操作的一种便捷语言
变量:出现在伪代码算法中的名字,引用了内存中的存储值位置。这些名字要能反映出他存放值的在算法中的角色
说白了就是个有名字要用的存储的一个东西,而且参与了算法
赋值
输入/输出
write输入read输出
选择
选择结构可以执行或跳过某项操作。此外,操作还可以在两项操作中做出选择具体看P119
//为省略部分,不参与程序中
缩进为对齐,而并非压缩,是表现while和else的一种表现方式、
重复
WHILE和IF旁边括号里的表达式是布尔表达式其中
IF里若表达式为假则跳过缩进代码块
WHILE中则为跳到下一个不缩进的语句中
布尔表达式(boolean expression):评价为真或假的表达式。
convert 转换
quotient 商
remainder 余数
6.5.3写伪代码算法
先把大致初稿定下 (not done) 和一些主干的书写
然后添加细节例如numberread+1
最后再次进行完善
先问了问题,后推迟细节的做法,被认定为分布解决
6.6测试
为了确保程序的是否正确,我们需要设计并实现一个测试计划
所谓测试计划就是一个文档,其中,每套测试输入的数据值称之为测试用例
测试用例一定要慎重选择,有几种测试方法可以作为测试过程的指导
代码覆盖(明箱)测试法通过执行代码中的所有语句测试程序
数据覆盖(暗箱)测试法把代码作为一个暗箱,基于所有可能的输入数据测试程序
测试计划实现
用测试计划中规定的测试用例验证程序是否输出了预期结果。
第七章:问题求解与算法设计
7.1如何解决问题
7.1.1提出问题
- 我对这个问题了解多少?
- 解决方案是什么样的?
- 存在什么特例?
- 我如何知道已经有解决方案了?
第一步
必须理解问题
理解问题
未知量是什么?数据是什么?条件是什么?条件有可能满足吗?抑或条件不够决定未知量吗?抑或条件是多余的?抑或条件是与未知量相矛盾的?绘制一幅图,引入合适的符号,把条件分割成多个部分,能把它写下来吗?
第二步
找到信息和解决方案之间的联系。如果找不到直接联系,则可能需要考虑辅助问题。最终,得到解决方案。
设计方案
以前见过这个问题吗?或者以前见过形式稍有不同的同样问题吗?知道相关的问题吗?知道可能解决这个问题的相关定理吗?仔细研究未知量,试想一个所熟悉的、具有同样未知量或相似未知量的问题。
有一个曾经解决过的相关问题。可以使用它吗?可以使用它的结果吗?可以使用它的方法吗?为了使用它,需要引入辅助元素吗?能复述问题吗?能换一个方式叙述问题吗?回到定义。如果不能解决这个问题,先尝试解决一些相关问题。可以想象一个比较容易解决的相关问题吗?一个更普适的问题?一个更专用的问题?一个相似的问题?可以解决部分问题吗? 只保留一部分条件,舍弃其他条件;未知量又明确了多少;它是如何变化的?能从数据得到一些有用的信息吗?可以想出另外一些能够确定未知量的数据吗?可以改变未知量或者数据,或者同时改变两者,使新数据和新未知量更接近吗?是否使用了所有数据?是否使用了所有条件?是否考虑到了该问题涉及到的所有关键概念?
第三步
执行方案。
执行方案
执行解决方案,检查每个步骤。可以清楚的看到每个步骤都正确吗?可以证明它是正确的吗?
第四步
分析得到的解决方案。
回顾
能检查结果吗?能检查参数吗?可以得到不同的结果吗?看到过这些结果吗?可以用这些结果和方法解决其他问题吗?
polya的如何解决它列表
7.1.2寻找熟悉的路径
算法:在有限的时间内用有限的数据解决问题或子问题的明确指令集合
7.1.3分治法
直到将抽象概念一直分解到可以执行为止。
7.1.4方法总结
1.分析问题
2.列出主要任务
3.编写其余的模块
4.根据需要进行重组和改写
7.1.5测试算法
7.2有简单参数的算法
7.2.1带有选择的算法
7.2.2带有循环的算法
- 计数控制循环
- 事件控制循环
嵌套结构:控制结构嵌入另一个控制结构的结构,又称为嵌套逻辑。
7.3复杂变量
7.3.1数组
数组是同构项目的有名集合
7.3.2记录
7.4搜索算法7.4搜索算法
7.4.1顺序搜索
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.1子程序语句
7.6.2递归阶乘
7.6.3递归二分检索
7.6.4快速检索7.6.4快速检索
7.7几个重要思想
7.7.1信息隐蔽
信息隐蔽:隐蔽模块的细节以控制对这些细节的访问的做法
7.7.2抽象
抽象:复杂系统中的模型,只包括对观察者来说必须的细节。
- 数据抽象
- 过程抽象
- 控制抽象
- 控制结构
7.7.3事物命名
7.7.4测试
QUESTION
为什么要把有关数据放在程序的前面?
源代码是干什么的?
”如果注释只是重复指令,这就不是好事了“ 关于这句话怎么理解?
有关循环程序理解不清楚