SICP练习题 1.3~1.8

1.3 求三个数字中的两个大数之和(不考虑相等情况)

(define (two-max-sum a b c)
  (cond
    ((and (< a b) (< a c)) (+ b c))
    ((and (< b a) (< b c)) (+ a c))
    (else
     (+ a b))))

1.5 检测应用序和正则序

(define (p) (p)   //此处定义的p是一个函数,而函数体是调用自己
(define (test x y)
  (if(= x 0)
      0
      y))                 

(test 0 (p))                     

应用序是先求值再展开,而正则序是先展开再求值。如果是应用序 (test 0 (p) )会先去求(p)的值,然而(p)是一个无限递归的一个函数,永远也无法结束。所以如果是应用序,则(test 0 (p)) 将永远都无法结束。如果是正则序:

 (test 0 (p)) 展开:
 (if (= 0 0)
   0
   (p))

(= 0 0 )返回#t
(p)被短路,所以(test 0 (p))返回 0额

1.6 new-if 代替 if问题

原题中,用new-if 函数代替if会产生死循环

(define (new-if predicate then-clause else-clause)
        (cond 
          (predicate then-clause)
          (else-clause)))

刚开始以为是cond和if有什么区别,发现new-if用if语句重新定义后依然还是死循环。后来明白了,if和new-if本质上是不同的。if和cond是条件表达式,new-if代表一个复合过程(函数)。根据应用序规则,new-if会在执行前,先计算出复合过程中的运算对象,然后将得到运算对象代入这个复合过程中。if和cond则会先判断条件,条件为真则执行第一个表达式,否则执行其他表达式。

下面是一个使用new-if和if的区别的例子

(define (p) (p)) //无限递归函数  

(if #t 1 (p)) //返回1,(p)被短路 

 (new-if #t 1 (p)) //无限递归

上面例子中,new-if 表达式中先会对(p)进行展开求值,因此会陷入无限递归

1.7 sqrt的改进

经过改进后对很小的数计算出的开方也非常精确

(define (good-enough? guess next)      //next 下一个猜测值
 (< abs (- 1 (/ guess next))) 0.001))  
(define (sqrt-iter guess x)
 (if (good-enough? guess (improve guess x))
    guess
    (sqrt-iter (improve guess x) x)))

 1.8 实现开立方根

代码经测试

(define (improve guess x)
 (/ (+ (/ x (* guess guess))
       (* 2 guess)) 3))

(define (good-enough? guess next)      //next 下一个猜测值
 (< abs (- 1 (/ guess next))) 0.001)) 

(define (open-cube-root-inter guess x)
 (if (good-enough? guess (improve guess x))
      guess
      (open-cube-root-inter (improve guess x) x)))

(define (open-cube-root x)
  (open-cube-root-inter 1 x)))

 另一种方式:(将辅助过程嵌套在主过程内部)

(define (open-cube-root x)
  (define (improve guess)
       (/ (+ (/ x (* guess guess))
       (* 2 guess)) 3))
  (define (good-enough? guess next)     
       (< abs (- 1 (/ guess next))) 0.001))
  
  (define (open-cube-root-inter guess)
    (if (good-enough? guess (improve guess x))
      guess
      (open-cube-root-inter (improve guess x) x)))

  (open-cube-root-inter 1.0 x))

注意:参数x作为其他辅助过程的自由变量,不需要在给辅助过程传递该参数

你可能感兴趣的:(SICP,lisp)