# 1.33

## 练习 1.33 你可以通过引进一个处理被组合项的过滤器（filter）概念，写出一个比accumulate（练习1.32）更一般的版本。也就是说，在计算过程中，只组合起由给定范围得到的项里的那些满足特定条件的项。这样得到的filtered-accumulate抽象取与上面累积过程同样的参数，再加上一个另外的描述有关过滤器的谓词参数。请写出filtered-accumulate作为一个过程，说明如何用filtered-accumulate表达以下内容：

a）求出在区间a到b中所有素数之和（假定你已经写出了谓词prime?）。

b）小于n的所有与n互素的正整数（即所有满足GCD(i, n)=1的整数i < n）之乘积。

a) 迭代实现：

(define (filtered-accumulate filter combiner null-value term a next b) (define (iter a result) (if (> a b) result (if (filter a) (iter (next a) (combiner result (term a ))) (iter (next a) result)))) (iter a null-value)) (define (always-true x) true) (define (accumulate combiner null-value term a next b) (filtered-accumulate always-true combiner null-value term a next b)) (define (sum term a next b) (accumulate + 0 term a next b)) (define (product term a next b) (accumulate * 1 term a next b)) (define (cube x) (* x x x)) (define (inc x) (+ x 1)) (sum cube 1 inc 10) (define (identity x) x) (product identity 1 inc 10) (define (smallest-divisor n) (find-divisor n 2)) (define (square x) (* x x)) (define (find-divisor n test-divisor) (cond ((> (square test-divisor) n) n) ((divides? test-divisor n) test-divisor) (else (find-divisor n (+ test-divisor 1))))) (define (divides? x y) (= (remainder y x) 0)) (define (prime? x) (= x (smallest-divisor x))) (prime? 1) (prime? 2) (prime? 3) (prime? 4) (define (sum-prime-numbers a b) (filtered-accumulate prime? + 0 identity a inc b)) (sum-prime-numbers 1 10) (+ 1 2 3 5 7)

b) 迭代实现：

(define (filtered-accumulate filter combiner null-value term a next b) (define (iter a result) (if (> a b) result (if (filter a) (iter (next a) (combiner result (term a ))) (iter (next a) result)))) (iter a null-value)) (define (always-true x) true) (define (accumulate combiner null-value term a next b) (filtered-accumulate always-true combiner null-value term a next b)) (define (sum term a next b) (accumulate + 0 term a next b)) (define (product term a next b) (accumulate * 1 term a next b)) (define (cube x) (* x x x)) (define (inc x) (+ x 1)) (sum cube 1 inc 10) (define (identity x) x) (product identity 1 inc 10) (define (smallest-divisor n) (find-divisor n 2)) (define (square x) (* x x)) (define (find-divisor n test-divisor) (cond ((> (square test-divisor) n) n) ((divides? test-divisor n) test-divisor) (else (find-divisor n (+ test-divisor 1))))) (define (divides? x y) (= (remainder y x) 0)) (define (prime? x) (= x (smallest-divisor x))) (prime? 1) (prime? 2) (prime? 3) (prime? 4) (define (sum-prime-numbers a b) (filtered-accumulate prime? + 0 identity a inc b)) (sum-prime-numbers 1 10) (+ 1 2 3 5 7) (define (gcd a b) (if (= b 0) a (gcd b (remainder a b)))) (define (product-prime-numbers-less-than n) (define (prime-to x) (= 1 (gcd x n))) (filtered-accumulate prime-to * 1 identity 1 inc (- n 1))) (product-prime-numbers-less-than 2) (product-prime-numbers-less-than 3) (product-prime-numbers-less-than 4) (product-prime-numbers-less-than 5) (product-prime-numbers-less-than 6) (product-prime-numbers-less-than 7) (product-prime-numbers-less-than 8) (product-prime-numbers-less-than 9) (product-prime-numbers-less-than 10)