SICP-Python版本(1.7)

因为无意中看见有人推荐的伯克利的这本教材,使用python教SICP,感觉使用起来更得心应手,毕竟scheme的括号太多用起来不习惯…虽然python不能支持所有的FP特性,但是作为一个初学者,让自己学起来有兴趣才是最重要的,以后全部都用Python来做啦!

(1) 首先用python实现一个抽象的Product,并用来定义一个计算
PI4=23434565....
这个PI的逼近式。代码如下:

主要就是注意要把(k+1/K)这个式子凑出来!

def product(n,term,next,initial):
    total,k = initial,0
    while k<=n:
        total,k = total*term(k),next(k)
    return total
def pi_next(k):
    return k+2
def pi_term(k):
    return ((k+4)/(k+3))**2
def pi_product(n=10**6):
    return product(n,pi_term,pi_next,8/(n+4))
print(pi_product())

(2)使f(x)=0.

首先只考虑两种形式的f(x):

通过这一层的抽象确定了f(x)的基本形式

def square_root(root):
    return find_root(lambda x:x*x-root)
def logarithm(a,base = 2):
    return find_root(lambda x:base**x - a)

接着定义find_root:

这一层的函数则是利用迭代改进过程来定义的

def find_root(f,initial_guess = 10):
    def test(x):
        return approx_eq(f(x),0)
    return iter_improve(newton_update(f), test, initial_guess)

再看迭代改进函数:

这其实是最抽象的一层了,在不满足条件的情况下不断的进行改善

def iter_improve(update, test, guess=1):
    while not test(guess):
        guess = update(guess)
    return guess

最后注意更新函数的定义:

这里的公式可以自行推导

def newton_update(f):
    def update(x):
        return x - f(x)/approx_derivative(f,x)
    return update
ef approx_derivative(f,x,delta = 1e-5):
    df = f(x+delta) - f(x)
    return df/delta
def approx_eq(a,b):
    if not a or b:return True
    return abs(a-b)<1e-5 and ( abs((a-b)/b) <1e-5 if b else abs((a-b)/a -1)<1e-5)

:

f=N1D1+N2D2+N3.......(1)

(a) :迭代计算:

def cont_frac(term_n,term_d,k):#compute the infinite fraction
    i,total = k,0
    while i!=0:
        total,i = term_n(i)/(total+term_d(i)),i-1
    return total
print(cont_frac(lambda i:1.0,lambda i:1.0,100))

(b) :递归计算

def rec_confrac(term_n,term_d,k):
    def contfrac(i):
        if i==k:return 0
        return term_n(i)/(term_d(i)+contfrac(i+1))
    return contfrac(0)

(c) :利用这个过程计算关于e的连分式:

Di=1,2,1,1,4,1,1,6,1,1,8,....;Ni=1

def compute_e(k):
    def term_d(i):
        if (i-2)%3:return 1
        else:return 2*((i-2)//3+1)
    return 2+cont_frac(lambda i:1,term_d,k)
print(compute_e(100))

:

def cubic(a,b,c):
    return find_root(lambda x:x**3+a*x**2+b*x+c)
print(cubic(0,-300,0))

:double,:

def repeat(f,n):
    def wrap(x):
        i = 1
        while i<=n:
            i,x = i+1,f(x)
        return x
    return wrap
def double(f):
    return repeat(f,n=2)
t = double(lambda x:x*5)

double(double(double))(lambdax:x+1)(5) 得到的结果是21。它的规律是每次都是上一次调用次数的平方。

f,repeatn .:
s(x)=average(f(xdx),f(x),f(x+dx))....

def abstract_smooth(f,average):
    def wrapper(x):
        dx = 1e-5
        return average(f,x,dx)
    return wrapper
def average3(f,x,dx):
    return (f(x)+f(x-dx)+f(x+dx))/3
def smooth(f):
    return abstract_smooth(f,average3)

def mul_smooth(f,n=3):
    return repeat(smooth,n)(f)
t = mul_smooth(lambda x:x**6 if x>=10 else 100)

你可能感兴趣的:(SICP学习笔记)