MIT 6.00 1x Lecture 3 - Simple Algorithms 简单算法 学习笔记

l MIT6.00 1x (麻省理工:计算机科学和Python编程导论)

Lecture 3 - Simple Algorithms 简单算法

3.1 iteration 迭代

Iteration 迭代

• Need one more concept to be able to writeprograms of arbitrary complexity 需要、更多的概念,能够写任意复杂的程序

– Start with a test  从测试开始

– If evaluates to True, then execute loop body once, and go back toreevaluate the test 如果是真,就向下执行一些指令,循环体,接着回去

– Repeat until test evaluates to False, after which code followingiteration statement is executed  重复,直到测试结果为假,跳过循环体,直接跳转到地方的运算


An example 一个例子

This code squares the value of x by repetitiveaddition. 此代码通过重复加法对x的值进行平方。

Stepping through this code 执行代码

Some properties of iteration loops:  循环迭代的一些性质

• need to set an iteration variable outsidethe loop  在循环外需要设置迭代变量

• need to test that variable to determinewhen done  需要测试变量,以便决定在什么时候结束

• need to change that variable within theloop, in addition to other work 需要改变循环中的变量,为了导向其他工作

Iterative code 迭代代码

• Branching structures (conditionals) letus jump to different pieces of code based on a test 分支结构(条件句)让我们跳到基于测试不同的代码块

– Programs are constant time  每个程序只执行一次

• Looping structures (e.g., while) let usrepeat pieces of code until a condition is satisfied    循环结构(例如,while)让我们重复代码,直到条件满足

– Programs now take time that depends on values of variables, aswell as length of program 

现在程序需要时间取决于变量的值,以及程序的长度

注:+=, -=, *=, /=代表什么?

is equivalent to 意思是等于

a += b is equivalent to a = a + b

a -= b is equivalent to a = a - b

a *= b is equivalent to a = a * b

a /= b is equivalent to a = a / b

提示:如果命令break在一个循环中被执行,它会在这个位置停止计算这个循环,然后传递控制权到下一个表达式。

3.2Guess and check algorithms 猜测和检查算法

Classes of algorithms  算法的种类

• Iterative algorithms allow us to do morecomplex things than simple arithmetic  迭代算法使我们能够比简单的算术做更复杂的事情

• We can repeat a sequence of stepsmultiple 0mes based on some decision; leads to new classes of algorithms  我们可以根据决定多次重复一些步骤,这开启了一个通往全新算法类别的大门

• One useful example are “guess and check”methods 一个非常有用例子是叫做“猜测检验的”方法

Guess and check 猜测检验

• Remember our “declarative” definition ofsquare root of x  记得我们之前的平方根的描述性的定义

• If we could guess possible values forsquare root (call it g), then can use definition to check if g*g = x  如果有人给出数字平方根的精确性猜测,我们可以用定义去检验他是否正确

• We just need a good way to generateguesses 我们所需的就是产生一个好猜测的方式

Finding a cube root of an integer 寻找整数的立方根

• One way to use this idea of generatingguesses in order to find a cube root of x is to first try 0**3, then 1**3, then2**3, and so on  我们可以利用猜测的方式,找到某数x的立方根,我们可以求1的立方根,2的立方根,3的立方根等等

• Can stop when reach k such that k**3 >x  直到k的立方比x大

• Only a finite number of cases to try 只有有限个情况需要尝试

Some code 一些代码

Extending scope 观察现象

• Only works for positive integers 这仅对正整数有效

• Easy to fix by keeping track of sign,looking for solu0on to positive case  我们可以回去并修复,然后我们可以相当直接的完成它。

Some code 一些代码

注:abs()函数表示这个数字的绝对值

Loop characteristics 循环特性

• Need a loop variable 需要一个循环变量

– Initialized outside loop 在循环的外部有一个循环变量的初始化

– Changes within loop  在循环内变化

– Test for termination depends on variable 根据该变量决定测试终止

• Useful to think about a decrementing function  对于递减函数十分有用

– Maps set of program variables into an integer  将程序变量映射到一个整数

– When loop is entered, value is non-negative  当循环输入一个值,这个值是非负的

– When value is <= 0, loop terminates, and 当这个值小于等于0时,这个循环就要停止

– Value is decreased every time through loop  每次循环中,数值都会下降

• Here we use abs(x) – ans**3 这里我们使用的是x的绝对值减ans的立方

What happens if we miss a condition? 如果我们做错了一个特性会发生什么

• Suppose we don’t initialize the variable? 假设我们没有外部初始化

• Suppose we don’t change the variableinside the loop? 假设我们在内部不变化这个变量

 结论:第一个错误会导致程序不能往下执行,第二个错误会导致程序无限执行

Exhaustive enumeration 穷举法

• Guess and check methods can work onproblems with a finite number of possibilities  猜测和检验方法对有限可能的问题有效

• Exhaustive enumeration is a good way togenerate guesses in an organized manner 详尽的枚举是一个有效的方式来生成猜测的好方法

3.3 LOOP MECHANISMS 循环机制

For loops   for循环

• While loops generally iterate over asequence of choices (ints in cases we have seen)  当型循环结构通常在一系列选择中进行迭代(通常,尤其是在穷举法中,一系列选择是一个按照顺序的完整序列

• Python has a specialized mechanism forthis case, called a for loop  Python将会提供一种非常有用的特殊循环机制来处理这一问题,它被称为for循环

for <identifier>in<sequence> 它的形式 for<标识符>in<序列(选择的集合)>:(以冒号结尾)

:<code block>  <缩进的代码块>

• Identifier bound to first value insequence  标识符最初会绑定到序列里的第一个值(即使前面绑定了别的数)

• Code block executed  运行代码块

• Identifier bound to next value  标识符会绑定到序列里的下一个值

• Code block executed  运行代码块

• Continues until sequence exhausted or a break statement is executed  重复上述执行过程,知道执行完所有的值或者遇到break语句

• To generate a sequence of integers, use  生成一个整数数列,用如下的函数

– range(n) = [0, 1, 2, 3, …, n-1]

– range(m,n) = [m, m+1, …, n-1]

 

注:range()函数

使用range函数的标准方法是给出一个终止值,然后range函数会从0开始直到终止值减一为止,给出一个数值列表。例如,调用rangestop)会生成如下: 

>>> range(5)

[0, 1, 2, 3, 4]

然而,我们可以用一些额外的可选参数——一个初始值和一个步长——来调用range函数。你可以指定一个初始值来调用rangestartstop),像这样: 

>>> range(2, 5)

[2, 3, 4]

定义一个步长,你必须知道那个一个初始值——调用命令为rangestart,stop,stepsize),像这样: 

>>> range(2, 10, 2)

[2, 4, 6, 8]

 

注:range()最后一个参数也可以使用负数,此时表示每次都减相应的步长,这时三个参数中第一个数应该比第二个数大

A cleaned up cube root finder 整理后的求立方根代码

3.4 FLOATING POINT ACCURACY 浮点精度

Dealing with floats 浮点数

• Floats approximate real numbers, butuseful to understand how  浮点数近似于真实的数,但是我们需要理解他是啥样的

• Decimal number:  十进制数

– 302 = 3*10**2 + 0*10**1 + 2*10**0

• Binary number  二进制数

– 10011 = 1*2**4 + 0*2**3 + 0*2**2 + 1*2**1 + 1*2**0

– (which in decimal is 16 + 2 + 1 = 19)  十进制数就是19

• Internally, computer represents numbersin binary 计算机内部使用2进制数来表示数

Remember: ** is Python’s exponentiationoperator  **在Python中是乘方的意思

Converting decimal integer to binary 将十进制数转化为二进制

• Consider example of  举个例子

– x = 1*2**4 + 0*2**3 + 0*2**2 + 1*2**1 + 1*2**0

• If we take remainder relative to 2 (x%2)of this number, that gives us the last binary bit  如果我们得到x除2的余数,它将告诉我们作为2进制的最后一位

• If we then divide x by 2 (x/2), all thebits get shifted left  再除以2,得到的余数是再往前一位的数值

– x/2 = 1*2**3 + 0*2**2 + 0*2**1 + 1*2**0 = 1001

• Keep doing successive divisions; nowremainder gets next bit, and so on 一步步往下除

• Let’s convert to binary form 我们就可以把十进制数转化为二进制

Doing this in Python 在python中写一下

 

注:Python3中整数相除得出来的是浮点数!!!!!!!!

 要记得再用一下int()函数!

So what about fractions? 那么小数呢

• 3/8 = 0.375 = 3*10**(-1) + 7*10**(-2) +5*10**(-3)

• So if we multiply by a power of 2 bigenough to convert into a whole number, can then convert to binary, then divideby the same power of 2  假设我们找到一个足够大的2的次幂,我们用这个小数乘它,会得到一个整数。然后我们就可以用刚才的方法了

• 0.375 * (2**3) = 3 (decimal) (十进制)

• Convert 3 to binary (now 11) 把3转化成二进制11

• Divide by 2**3 (shift left) to get 0.011(binary) 11除以2**3或者移位就可以得到0.011

 

倒数第三句 我用的是result=”0.”+result[-p:]

Some implications 启示

• If there is no integer p such thatx*(2**p) is a whole number, then internal representation is always anapproximation  如果没有整数p使得x*(2**p)是个是个整数,那么内部代表将一直是一个近似值

• Suggest that testing equality of floatsis not exact  结论是浮点数的相等时不精确的

– Use abs(x-y) < 0.0001, rather than x == y

• Why does print(0.1) return 0.1, if notexact?  为什么输入0.1就返回0.1,它不是不精确的么

– Because Python designers set it up this way to automatically round因为Python设计师是这样设计的

 

注:在机器内部!0.1不一定就是精确地0.1

3.5 APPROXIMATION METHODS 近似方法(穷举法)

Approximate solutions 近似解

• Suppose we now want to find the squareroot of any non-negative number?  假设我们想找到任何非负数的平方根

• Can’t guarantee exact answer, but justlook for something close enough  不需要确保得到准确的答案,只求近似解

• Start with exhaustive enumeration  从详尽的枚举开始

– Take small steps to generate guesses in order  采取小步骤,按顺序产生所有猜测

– Check to see if close enough 检查是否足够接近

Example code 举例代码

Some observations 一些观察

• Step could be any small number  步长可以是任意小的数

– If too small, takes a long time to find square root  如果他太小的话,我们将会花费较长的时间找到平方根

– If make too large, might skip over answer without getting closeenough  如果太大的话,我们可能回错过接近的解,(步数太大精度太小)

• In general, will take x/step timesthrough code to find solution  总的来说,它将花费x/步长 的时间在寻找答案

• Need a more efficient way to do this 需要一个更有效的方法来做这件事

3.6 BISECTION SEARCH 二分法查找

Bisection search  二分法查找

• We know that the square root of x liesbetween 0 and x, from mathematics  从数学上我们知道x的平方根介于0和x之间

• Rather than exhaustively trying thingsstarting at 0, suppose instead we pick a number in the middle of this range  不同于穷举法我们从0开始穷举,二分法让我们从范围的中间中选择一个数

• If we are lucky, this answer is closeenough 如果我们幸运,g就足够接近平方根

• If not close enough, is guess too big ortoo small?  如果不接近的话,猜测是大是小啊

• If g**2 > x, then know g is too big;but now search  如果g方大于x,则g偏大

• And if this new g is, for example, g**2< x, then know too small; so now search  new g方小于x

• At each stage, reduce range of values tosearch by half 每个阶段,范围都减小一半

Example of square root 求平方根的例子

Some observations 一些观察

• Bisection search radically reducescomputation time  二分查找从根本上减少了计算的次数

– being smart about generating guesses is important  聪明的猜测是很智能的

• Should work well on problems with“ordering” property  它非常适用于拥有排序属性的问题

– value of function being solved varies monotonically with inputvalue  待求得数值仅随输入值变化

– Here function is g**2; which grows as g grows 这里g的平方仅随g的增长而增长

3.7 NEWTON-RAPHSON ROOT FINDING牛顿-拉夫逊多项式求根

Newton-Raphson 牛顿-拉夫逊

• General approximation algorithm to findroots of a polynomial in one variable  在一个变量中找到多项式的根的一般逼近算法

p(x)= anxn + an-1xn-1 + … + a1x+ a0

• Want to find r such that p(r) = 0  我们希望找到一个r是p(r)=0

• For example, to find the square root of24, find the root of p(x) = x2 – 24  举个例子,我们想找到24的平方根仅需使p(x) = x2 – 24

• Newton showed that if g is an approximationto the root, then  牛顿发现 如果g是一个近似的根,则

g –p(g)/p’(g)

is a better approximation; where p’ isderivative of p   是一个更好的近似值,p’是p的导数

• Simple case: cx2 + k   简单的案例

• First derivative: 2cx     一阶导数

• So if polynomial is x2 + k,then derivative is 2x  所以如果多项式是x2+k,导数是2x

• Newton-Raphson says given a guess g forroot, a better guess is g – (g2 –k)/2g 这个算法说给你要给出猜测的解g,则g – (g2 –k)/2g是更近似的解

• This gives us another way of generatingguesses, which we can check; very efficient 这给你我们一种新的产生猜测的方式,而且这个更有效

Iterative algorithms 迭代算法

• Guess and check methods build on reusingsame code  我们使用相同重复的代码建立猜测和检查方法

– Use a looping construct to generate guesses, then check and continue 我们使用循环的方法产生猜测,然后检查,然后继续

• Generating guesses  产生猜测(三种方法)

– Exhaustive enumeration  穷举法

– Bisection search  二分法

– Newton-Raphson (for root finding) 牛顿-拉夫逊法(找多项式的根)

 

 

注:Python中  / 这个符号可以用来把太长的一行分割成两行

总结

    介绍了迭代的概念,,学习了猜测检验方法,引出了循环结构,还介绍了产生猜测的三种方法,穷举法,二分法,牛顿-拉夫逊法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值