首页 > 代码库 > SICP 1.23-1.26体会

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)))))

SICP 1.23-1.26体会