穷举法
:是猜测与检验算法的一个变种。我们枚举所有可能性,直至得到正确答案或者尝试完所有值。
#寻找完全立方数的立方根
x = int(input('Enter an integer: '))
ans = 0
while ans**3 < abs(x):
ans = ans + 1
if ans**3 != abs(x):
print(x, 'is not a perfect cube')
else:
if x < 0:
ans = -ans
print('Cube root of', x,'is', ans)
那么,对于何种x值,程序能正常结束呢?答案是“所有整数”。
注
:
1.表达式ans**3的值从0开始,并随着每次循环逐渐变大;
2.当这个值达到或超过abs(x)时,循环结束;
3.因为abs(x)的值总为正,所以循环结束前进行的迭代次数必然是有限的。编写循环时,应该使用一个合适的递减函数。这个函数具有如下属性:
for循环中常用到range()函数
,因此先对它进行介绍:
#寻找完全立方数的立方根
x = int(input('Enter an integer: '))
for ans in range(0, abs(x)+1):
if ans**3 >= abs(x):
break
if ans**3 != abs(x):
print(x, 'is not a perfect cube')
else:
if x < 0:
ans = -ans
print('Cube root of', x,'is', ans)
穷举法
是一种查找技术,只在被查找集合中包含答案时才有效
#使用穷举法求近似平方根
x = 25
epsilon = 0.01
step = epsilon**2
numGuesses = 0
ans = 0.0
while abs(ans**2 - x) >= epsilon and ans <= x:
ans += step
numGuesses += 1
print('numGuesses =', numGuesses)
if abs(ans**2 - x) >= epsilon:
print('Failed on square root of', x)
else:
print(ans, 'is close to square root of', x)
二分查找法
,可以提升查询效率
x = 25
epsilon = 0.01
numGuesses = 0
low = 0.0
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 - x) >= epsilon:
print('low =', low, 'high =', high, 'ans =', ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print('numGuesses =', numGuesses)
print(ans, 'is close to square root of', x)
很多时候,float类型
的数值是实数的一个非常好的近似
。但“很多时候”并不代表所有情况,这个功能失效时会引起不可思议的后果。例如,试着运行以下代码:
x = 0.0
for i in range(10):
x = x + 0.1
if x == 1.0:
print(x, '= 1.0')
else:
print(x, 'is not 1.0')
# 结果
0.9999999999999999 is not 1.0
为什么会出现这样的结果呢?
牛顿-拉弗森法
可以用于求单变量多项式的值,那么什么是单变量多项式?
单变量多项式或者是0,或者是一个有限数目的非零单项式的和。每一项都由一个常数(项的系数)乘以变量的非负整数次方(这里为2次方)组成。
牛顿-拉弗森法的原理
:
逐次逼近;牛顿证明了一个定理:如果存在一个值guess是多项式p的根的近似值,那么guess -p(guess)/p’(guess)就是一个更好的近似值,其中p’是p的一次导数。
#利用牛顿.拉弗森法寻找平方根
#寻找x,满足x**2-24在epsilon和0之间
epsilon = 0.01
k = 24.0
guess = k/2.0
while abs(guess*guess - k) >= epsilon:
guess = guess - (((guess**2) - k)/(2*guess))
print('Square root of', k, 'is about', guess)
1.编写一个程序,要求用户输入一个整数,然后输出两个整数root和pwr,满足0
root**pwr
等于用户输入的整数。如果不存在这样一对整数,则输出一条消息进行说明。
# 解法1
r = int(input('input an integer'))
root = 0
i = 0
for pwr in range(1, 7):
result = -1
while result < abs(r):
root += 1
result = root**pwr
if result == abs(r):
if r < 0:
root = -root
print('root:{},pwr:{}'.format(root, pwr))
i += 1
root = 0
print('总共有{}种输出结果'.format(i))
# 解法2
x=int(input('Enter an integer: '))
root=1
pwr=1
w=root**pwr
i=0
while w<abs(x) or root<=abs(x):
if pwr<6:
w=root**pwr
if w==abs(x) and x<0:
i+=1
print('root','=',-root,'pwr','=',pwr)
elif w==abs(x):
i+=1
print('root','=',root,'pwr','=',pwr)
pwr+=1
else:
pwr=1
root+=1
w=root**pwr
print('符合条件的整数对共有{}种'.format(i))
2.假设s是包含多个小数的字符串,由逗号隔开,如s = '1.23, 2.4, 3.123'
。编写一个程序,输出s中所有数值的和。
# 解法1
s = '1.23, 2.4, 3.123'
sum = 0.0
for i in map(lambda i: float(i), s.split(',')):
sum += i
print(sum)
# 解法2
s = '1.23, 2.4, 3.123'
a=s.split(',')
t=0
for i in a:
t=t+float(i)
print(t)
3.如果语句x = 25被替换为x = -25,代码会如何运行?
程序会进入无限循环
# 该程序while循环中,x值始终未变。则导致该循环条件(abs(ans**2 - x) >= epsilon)始终成立,程序进入无限循环中。
x = -25
epsilon = 0.01
numGuesses = 0
low = 0.0
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 - x) >= epsilon: # 这一步永远不会停止
print('low =', low, 'high =', high, 'ans =', ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print('numGuesses =', numGuesses)
print(ans, 'is close to square root of', x)
4.如何修改图3-4中的代码,才能求出一个数的立方根?这个数既可以是正数,也可以是负数。(提示:修改low保证答案位于待查找区域。)
x = -30
epsilon = 0.01
numGuesses = 0
x_abs = abs(x) # 关键代码
low = 0.0
high = max(1.0, x_abs)
ans = (high + low) / 2.0
while abs(ans**3 - x_abs) >= epsilon:
numGuesses += 1
if ans**3 < x_abs:
low = ans
else:
high = ans
ans = (high + low) / 2.0
print('numGuesses =', numGuesses)
if x < 0:
print(-ans, 'is close to square root of', x)
else:
print(ans, 'is close to square root of', x)
5.二进制数10011等于十进制中的哪个数?
19
# 解法1 进制转换
# 解法2 函数求解
int('10011',base=2)
6.在牛顿.拉弗森法的实现中添加一些代码,跟踪求平方根所用的迭代次数。在这段代码的基础上编写一个程序,比较牛顿.拉弗森法和二分查找法的效率。
#利用牛顿.拉弗森法寻找平方根
#寻找x,满足x**2-24在epsilon和0之间
epsilon = 0.01
k = 24.0
guess = k/2.0
a=0
while abs(guess*guess - k) >= epsilon:
guess = guess - (((guess**2) - k)/(2*guess))
a+=1
print('Square root of', k, 'is about', guess)
print('牛顿法迭代次数={}'.format(a))
#利用二分查找法寻找平方根
#寻找x,满足x**2-24在epsilon和0之间
x = 24.0
epsilon = 0.01
numGuesses = 0
low = 0.0
high = max(1.0, x)
ans = (high + low)/2.0
b=0
while abs(ans**2 - x) >= epsilon:
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print(ans, 'is close to square root of', x)
print('二分法迭代次数 ={}'.format(numGuesses))
Square root of 24.0 is about 4.8989887432139305
牛顿法迭代次数=4
4.8984375 is close to square root of 24.0
二分法迭代次数 =9