SICP 1.23-1.26体会

1.23 代码改动很简单, 关键是时间。 电脑上算了一下, 100000000以下全是0, 开始还以为代码写错了。

最后没办法, 用1e10 1e11来计算, 发现比 1e11 1e12快1.2-1.5之间。比2小。想了半天也给不出很合理的解析。

开始以为是对3 5 7 取余数 比 4 6 8 要慢, 测试了一下,发现也不是这么一回事。网上有人怀疑是函数调用花了一定时间做if 判断, 老实说这东西性能影响也不应有这么大。

现在唯一想到的,就是编译器做了一些优化,导致性能不完全取决于调用次数。

这题目,网上也没找到很合理的分析。

1.24  也很遗憾, 开始将times设为10, 计算时间1e10以下完全是0. 后面没办法,将times设为10000, 结果发现时间也很漂浮不定。

有时候, 1e12-1e13 比 1e11-1e12计算速度还快。 只能说random导致性能很随机了。

1.25 理论上肯定是对的, 时间上就悲剧了。我这边执行 100000000 1000000000区间,直接死机。

根本原因,还是我们的CPU是32或64位的, 不是无限位。

1.26 这个题目算法导论有清晰的解析。套用算法导论的公式T(n) = 2T(n/2) 可知道 T(n) = Theta(n)

坦率地说, SICP不是学算法的好书。 也不是讲数据结构的好书。

个人代码如下:

1.23

(define (search-for-primes-new start end count)

(define (timed-prime-test n)

(newline)

(display n)

(start-prime-test n (runtime)))

(define (start-prime-test n start-time)

(if (prime? n)

(report-prime (- (runtime) start-time))

0))

(define (report-prime elapsed-time)

(display " *** ")

(display elapsed-time)

1)

(define (prime? n)

(= n (smallest-divisor-new n)))

(define (smallest-divisor-new n)

(define (find-divisor n test-divisor)

(cond ((> (square test-divisor) n) n)

((divides? test-divisor n) test-divisor)

(else (find-divisor n (next test-divisor)))))

(define (divides? a b)

(= (remainder b a) 0))

(define (next test-divisor)

(if (= test-divisor 2)

3

(+ test-divisor 2)))

(find-divisor n 2))

(define (search-iter start end count)

(if (or (> start end) (= count 0))

0

(if (= (timed-prime-test start) 1)

(search-iter (+ start 1) end (- count 1))

(search-iter (+ start 1) end count))))

(search-iter start end count))

1.24

(define (search-for-primes-new start end count)

(define (timed-prime-test n)

(newline)

(display n)

(start-prime-test n (runtime)))

(define (start-prime-test n start-time)

(if (fast-prime? n 10000)

(report-prime (- (runtime) start-time))

0))

(define (report-prime elapsed-time)

(display " *** ")

(display elapsed-time)

1)

(define (search-iter start end count)

(if (or (> start end) (= count 0))

0

(if (= (timed-prime-test start) 1)

(search-iter (+ start 1) end (- count 1))

(search-iter (+ start 1) end count))))

(search-iter start end count))

(define (expmod base exp m)

(cond ((= exp 0) 1)

((even? exp)

(remainder (square (expmod base (/ exp 2) m))

m))

(else

(remainder (* base (expmod base (- exp 1) m))

m))))

(define (fast-prime? n times)

(cond ((= times 0) true)

((fermat-test n) (fast-prime? n (- times 1)))

(else false)))

(define (fermat-test n)

(define (try-it a)

(= (expmod a n n) a))

(try-it (+ 1 (random (- n 1)))))

1.25

(define (search-for-primes-25 start end count)

(define (timed-prime-test n)

(newline)

(display n)

(start-prime-test n (runtime)))

(define (start-prime-test n start-time)

(if (fast-prime? n 10000)

(report-prime (- (runtime) start-time))

0))

(define (report-prime elapsed-time)

(display " *** ")

(display elapsed-time)

1)

(define (search-iter start end count)

(if (or (> start end) (= count 0))

0

(if (= (timed-prime-test start) 1)

(search-iter (+ start 1) end (- count 1))

(search-iter (+ start 1) end count))))

(search-iter start end count))

(define (expmod base exp m)

(remainder (fast-expt base exp) m))

(define (fast-expt base exp)

(cond ((= exp 0) 1)

((even? exp)

(square (fast-expt base (/ exp 2))))

(else

(* base (fast-expt base (- exp 1))))))

(define (fast-prime? n times)

(cond ((= times 0) true)

((fermat-test n) (fast-prime? n (- times 1)))

(else false)))

(define (fermat-test n)

(define (try-it a)

(= (expmod a n n) a))

(try-it (+ 1 (random (- n 1)))))

时间: 2024-08-27 11:15:28

SICP 1.23-1.26体会的相关文章

SICP 1.25 1.26

解: 1.25 这么写的话a的n次方会很大,大数需要额外的处理.原始的expmod基于这个结论: (a*b)%c=((a%c)*(b%c))%c,证明如下: 设a=nc+k,b=mc+h,则 (a*b)%c=((nc+k)*(mc+h))%c=(nmc^2+nhc+mkc+kh)%c=(k*h)%c=((a%c)*(b%c))%c 1.26 这么写没有使计算量逐步减半. SICP 1.25 1.26,布布扣,bubuko.com

SICP 习题 (2.26)解题总结:列表操作符append cons list

SICP  习题 2.26 也是不需要太多解释的题目, 题目的主要目的是让读者理解append cons list三个操作的差别. 直接运行下面代码中的start-test-2-26过程就可以了,需要留意一下的是append 过程, cons过程和list过程的使用. 最好翻一下mit-schme的参考手册,对了,一直没有提mit-scheme的手册,建议大家去下载一份备用,需要的时候查一查 链接如下: http://www.gnu.org/software/mit-scheme/ 有pdf版可

SICP 1.34-1.39习题体会

1.34 代入法, 报错, 2不能作为操作符 1.35 证明比较简单,因为它为方程的根.代码也就是将书本代码重写一遍. (define (fix-point f first-guess) (define tolerance 0.00001) (define (close-enough? v1 v2) (< (abs (- v1 v2)) tolerance)) (define (try guess) (let ((next (f guess))) (if (close-enough? guess

SICP 1.27 1.28体会

这2题目, 还算比较简单. 做了3天的题,最大的痛苦就是还不大会调试, 所有代码均靠大脑分析,太痛苦了. 最坑的就是, 经常漏函数参数, load的时候系统也不报错, 运行时的错误提示又如同天书, 看来还是先要找本讲scheme的书先学习下,否则效率太低了. 1.27 主要是写个迭代代码, 测试所有2到n-1.代码如下: (define (prime-test n) (define (prime-test-iter start end) (if (> start end) true (if (f

SICP 1.21 1.22 体会

1.21 简单的将书上代码敲了一遍. 非常顺利就过了. 1.22 就悲剧了. 先按书本的意思.代码非常快就写完了.但计算的时间在机子上漂浮不定. 3-5倍之间. 代码例如以下: (define (search-for-primes start end count) (define (timed-prime-test n) (newline) (display n) (start-prime-test n (runtime))) (define (start-prime-test n start-

SICP 习题1.16-1.19体会

首先反思一下, 昨天做1.14的时候犯了一个严重错误,思维定式了,导致花了很多无用功. 1.14的关键是要想到2个物理意义. 一个是广度优先, 也就是只考虑问题递归树的第一层子数.那么必然有公式 F(n,m) = F(n- c1, m) + ... + F(n-cm, m) + 1   c1..cm为货币价值, m为货币树. 利用这个公式,我们很容易用数学归纳法证明存在一个参数C1,满足F(n,m) > C1 * n的m次方. 但是,利用这个公式,我们是无法证明存在一个参数C2,满足F(n,m)

2018.9.26 如何对List集合中的元素进行排序?

Collections对List集合中的数据进行排序 有时候需要对集合中的元素按照一定的规则进行排序,这就需要用到 Java中提供的对集合进行操作的工具类Collections,其中的sort方法 先看一个简单的例子: [java] view plain copy public static void main(String[] args) { List nums = new ArrayList(); nums.add(3); nums.add(5); nums.add(1); nums.add

最佳vim技巧

最佳vim技巧----------------------------------------# 信息来源----------------------------------------www.vim.org         : 官方站点comp.editors        : 新闻组http://www.newriders.com/books/opl/ebooks/0735710015.html : Vim书籍http://vimdoc.sourceforge.net/cgi-bin/vim

泰坦尼克号电影 完整字幕 中英文对比 完整版

0,0:01:50.93,0:01:53.03Thirteen meters. You should see it. 距离13公尺 应该看得见了 0,0:02:05.73,0:02:08.03Okay, take her up and over the bow rail. 越过船头的栏杆 0,0:02:09.53,0:02:12.73Okay, Mir- 2, we're going over the bow. Stay with us. 和平二号 我们要到船头了 跟好 0,0:02:45.63