免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: win_hate
打印 上一主题 下一主题

SICP 习题参考答案 3.1  关闭 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2008-12-06 22:34 |只看该作者

Exerciese 3.5. 答案


  1. (define (monte-carlo trials experiment)
  2.   (define (iter trials-remaining trials-passed)
  3.     (cond ((= trials-remaining 0)
  4.            (/ trials-passed trials))
  5.           ((experiment)
  6.            (iter (- trials-remaining 1) (+ trials-passed 1)))
  7.           (else
  8.            (iter (- trials-remaining 1) trials-passed))))
  9.   (iter trials 0))
  10.             
  11. (define (random-in-range low high)
  12.   (let ((range (- high low)))
  13.     (+ low (random range))))

  14. (define (test x y)
  15.   (<= (+ (* x x) (* y y)) 1))

  16. (define (estimate-integral test x1 x2 y1 y2 n)
  17.   (let ((f (lambda ()
  18.              (test (random-in-range x1 x2)
  19.                    (random-in-range y2 y1)))))
  20.     (* (monte-carlo n f) (* (- x2 x1) (- y1 y2)))))
复制代码


测试


  1. guile> (estimate-integral test -1.0 1.0 1.0 -1.0 10000)
  2. 3.1512
  3. guile> (estimate-integral test -1.0 1.0 1.0 -1.0 10000)
  4. 3.1364
  5. guile> (estimate-integral test -1.0 1.0 1.0 -1.0 10000)
  6. 3.1496
  7. guile> (estimate-integral test -1.0 1.0 1.0 -1.0 10000)
  8. 3.1244
  9. guile> (estimate-integral test -1.0 1.0 1.0 -1.0 10000)
  10. 3.1556
  11. guile> (estimate-integral test -1.0 1.0 1.0 -1.0 10000)
  12. 3.12
  13. guile> (estimate-integral test -1.0 1.0 1.0 -1.0 10000)
  14. 3.1508
复制代码

[ 本帖最后由 win_hate 于 2008-12-6 22:37 编辑 ]

论坛徽章:
0
12 [报告]
发表于 2008-12-06 22:37 |只看该作者

Exerciese 3.6.

Exercise 3.6.  It is useful to be able to reset a random-number generator to produce a sequence starting from a given value. Design a new rand procedure that is called with an argument that is either the symbol generate or the symbol reset and behaves as follows: (rand 'generate) produces a new random number; ((rand 'reset) <new-value>) resets the internal state variable to the designated <new-value>. Thus, by resetting the state, one can generate repeatable sequences. These are very handy to have when testing and debugging programs that use random numbers.

论坛徽章:
0
13 [报告]
发表于 2008-12-06 22:48 |只看该作者
书本这个题目出得不是太好。因为在书里没有介绍随机数生成的理论。所以要做这个题目有两个选择,一是用 scheme 中现成的函数,另一个选择是自己去学一下随机数生成算法。

在这里,我使用线性同余来产生随机数。公式为


  1. x(0)=1
  2. x(n+1)=x(n)*16807    (mod 2147483647)
复制代码


  1. (define (make-random)
  2.   (let ((state 1)
  3.         (a 16807)
  4.         (m 2147483647))
  5.     (define rand
  6.       (lambda (cmd)
  7.         (cond ((eq? cmd 'generate)
  8.                (let ((r (modulo (* a state) m)))
  9.                  (set! state r)
  10.                  r))
  11.               ((eq? cmd 'reset)
  12.                (lambda (seed)
  13.                  (set! state seed)))
  14.               (else
  15.                (error "Not implement ---" cmd)))))
  16.     rand))
  17.    
  18. (define rand (make-random))
复制代码


测试:


  1. > (map rand (list 'generate 'generate 'generate 'generate))
  2. (16807 282475249 1622650073 984943658)

  3. > ((rand 'reset) 1)    ;; 把内部状态重设为 1

  4. > (map rand (list 'generate 'generate 'generate 'generate))
  5. (16807 282475249 1622650073 984943658)    ;; 产生相同的序列

  6. > ((rand 'reset) 1622650073)    ;; 把内部状态设置为 1622650073,下一个会是 984943658

  7. > (rand 'generate)
  8. 984943658
复制代码

[ 本帖最后由 win_hate 于 2008-12-6 22:50 编辑 ]

论坛徽章:
0
14 [报告]
发表于 2008-12-10 13:08 |只看该作者

Exercise 3.7.

Exercise 3.7.  Consider the bank account objects created by make-account, with the password modification described in exercise 3.3. Suppose that our banking system requires the ability to make joint accounts. Define a procedure make-joint that accomplishes this. Make-joint should take three arguments. The first is a password-protected account. The second argument must match the password with which the account was defined in order for the make-joint operation to proceed. The third argument is a new password. Make-joint is to create an additional access to the original account using the new password. For example, if peter-acc is a bank account with password open-sesame, then

(define paul-acc
  (make-joint peter-acc 'open-sesame 'rosebud))

will allow one to make transactions on peter-acc using the name paul-acc and the password rosebud. You may wish to modify your solution to exercise 3.3 to accommodate this new feature.

论坛徽章:
0
15 [报告]
发表于 2008-12-10 13:21 |只看该作者

Exercise 3.7. 答案


  1. (define (make-account balance password)
  2.   (define (withdraw amount)
  3.     (if (>= balance amount)
  4.         (begin (set! balance (- balance amount))
  5.                balance)
  6.         "Insufficient funds"))
  7.   
  8.   (define (deposit amount)
  9.     (set! balance (+ balance amount))
  10.     balance)

  11.   (define (share newpass)
  12.     (dispatch newpass))

  13.   (define (dispatch password)
  14.     (lambda (pass m)
  15.       (cond ((not (eq? password pass)) (lambda (x) "Incorrect password"))
  16.               ((eq? m 'withdraw) withdraw)
  17.               ((eq? m 'deposit) deposit)
  18.               ((eq? m 'share) share)
  19.               (else (error "Unkonwn request -- MAKE-ACCOUNT" m)))))
  20.   
  21.   (dispatch password))
  22.    
  23. (define (make-joint acc pass newpass)
  24.   ((acc pass 'share) newpass))
复制代码


在 3.3 的基础上修改得到的。为 dispatch 增加了局部变量。

测试:


  1. > (define acc1 (make-account 100 'xxx))
  2. > (define acc2 ((acc1 'xxx 'share) 'yyy))
  3. > (define acc3 ((acc1 'xxx 'share) 'zzz))
  4. > (define acc4 ((acc3 'zzz 'share) 'www))
  5. > (define t1 (acc1 'xxx 'withdraw))
  6. > (define t2 (acc2 'yyy 'withdraw))
  7. > (define t3 (acc3 'zzz 'withdraw))
  8. > (define t4 (acc4 'www 'withdraw))
  9. > (t1 10)
  10. 90
  11. > (t2 10)
  12. 80
  13. > (t3 10)
  14. 70
  15. > (t4 10)
  16. 60
  17. > (define p4 (acc4 'www 'deposit))
  18. > (define p3 (acc3 'zzz 'deposit))
  19. > (p4 1000)
  20. 1060
  21. > (p3 10000)
  22. 11060
复制代码

[ 本帖最后由 win_hate 于 2008-12-10 21:16 编辑 ]

论坛徽章:
0
16 [报告]
发表于 2008-12-10 13:22 |只看该作者

Exercise 3.8.

Exercise 3.8.  When we defined the evaluation model in section 1.1.3, we said that the first step in evaluating an expression is to evaluate its subexpressions. But we never specified the order in which the subexpressions should be evaluated (e.g., left to right or right to left). When we introduce assignment, the order in which the arguments to a procedure are evaluated can make a difference to the result. Define a simple procedure f such that evaluating (+ (f 0) (f 1)) will return 0 if the arguments to + are evaluated from left to right but will return 1 if the arguments are evaluated from right to left.

论坛徽章:
0
17 [报告]
发表于 2008-12-10 13:25 |只看该作者

3.8 答案


  1. (define f
  2.   (let ((s 1))
  3.     (lambda (x)
  4.       (set! s (* s x))
  5.       s)))
复制代码


  1. > (load "3.8.scm")
  2. > (+ (f 0) (f 1))
  3. 0
复制代码


  1. > (load "3.8.scm")
  2. > (+ (f 1) (f 0))
  3. 1
复制代码

论坛徽章:
0
18 [报告]
发表于 2008-12-10 13:25 |只看该作者
本节完。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP