要学好计算机,就要学会像计算机一样思考。
对于一个数 x = 9 ,求,你会毫不犹豫地回答3;如果 x = 784 ?你也能在第一时间说出答案吗?
计算机并不像人一样聪明,它只能按照事先规定好的步骤一步一步地进行, 我们称之为算法,算法的魅力就在于能够指导计算机快速精确地解决问题。
以下介绍三种开平方算法。
①穷举法(屎一样的算法,建议从后两个算法看起):
当人看到x = 9 ,求时,它会首先在大脑里搜索是否存在直接能用的结果,相信九九乘法表早已刻在你的脑子里,因此你会毫不犹豫地说出, = 3;但是当x = 784时,你的脑中不存在的直接储备,但是你记得25的平方与30的平方这两个节点,而784恰好处在625与900之间,因此,如果运气够好的话,只需要计算26、27、28、29的平方,当然,你的运气足够好, = 28.
好了,现在我们将784更换成744,你又如何做呢?显然经过计算你又知道了在27,28之间,是一个小数,因此你需要猜测,小数点后那一位究竟是多少。
现在,我们用代码模拟以上过程。需要解决以下几个问题:
①为了让计算机快速找到解区间,你需要一个乘法表来存储各个关键节点,那么这个表应该多大呢?如果一个好事者输入了10位整数,我们的计算机能够存储那么大的乘法表吗?
既然这样,不如利用计算机的优势,当场算出相应的区间就好。
②猜测的小数后一位应该是多少呢?
既然找到了区间,不如设定一个步长假设为0.1,依次计算区间内的数据。(27.1,27.2,27.3······)
显然步长越小,计算次数越多。
③计算机无法精确表达浮点数,只能通过设置误差a来确定是否取值(abs(i^2) - x < a),这时你惊奇的发现
27.2^2 = 739.84
27.3^2 = 745.29
因此误差a至少要取到1.29,如果我们设置a = 1,那么就无法得到答案。
如果步长与误差设置不合适,很可能计算机会跳过正确的解。
以上的问题搞得人焦头烂额,让人感觉像食屎一样。
因此很不负责任地得到以下代码(Python为例)
x = int(input("请输入一个数字:"))
i = 0
const = 0
while(i**2 < x):
i+=1
const+=1
i -= 1
while(i**2<x):
i+=0.01
const+=1
print("sqrt(x) = %f,const = %d"%(i,const))
当输入x = 15 sqrt(x) = 3.880000,const = 92
当x = 1928332946 sqrt(x) = 43912.790000,const = 43992
②:二分法
实际上,对于一个数x,其解必定在(0,x)之间,那么将x/2作为猜测值,若大了,说明解在区间(0,x/2)之间,若小了,说明解在区间(x/2,x)。
x = float(input("请输入数字:"))
left = 0.0
right = x
a = 0.001
i = x/2
const = 0 #计步
while(abs(i**2 - x) > a): #当i^2与x误差小于0.001,退出循环
if(i**2 - x < 0):
left = i
i +=(right-left)/2 #如果真实解在右侧区间,则更新i为新区间中点
const+=1
else:
right = i
i -=(right-left)/2 #如果真实解在左侧区间,更新i为新区间中点
const+=1
print("sqrt(x) = %f,const = %d"%(i,const))
当x = 15,sqrt(x) = 3.872910,const = 15
x = 1928332946,sqrt(x) = 43912.787955,const = 55
可见精度与运算速度均有极大提高。(算法的魅力)
③牛顿法(姑且这么称呼):
根据牛顿的理论
对于多项式 P(x) = a*(x^n)+b*(x^(n-1))+c*(x^(n-2))······
若存在近似值r,使得P(r)≈ 0,那么 r - P(r)/P'(r) 的值将比 r 更加接近 真实解 的值。
那么如何使用呢?
对于求24的平方根,我们可以设P(x)=x^2 - 24,那么P‘(x) = 2*x
这样对于近似值r,设置r = r - (r^2-24)/2*r,这样不断迭代,就可以更加快速地得到近似值。
代码如下:
x = float(input("请输入数字:"))
i = x/2
a = 0.0001 #注意这里误差为二分法的0.1倍
const = 0 #计步
while(abs(i**2 - x) > 0.001):
i = i - ((i**2-x)/(2*i))
const+=1
print("sqrt(x) = %f,const = %d"%(i,const))
当 x = 15 ,sqrt(x) = 3.872983,const = 4
当x = 1928332946,sqrt(x) = 43912.787955,const = 19
代码更加简洁,精度与运算速度再次提高!