Be careful to use the provided constructors, rather than using stream operators!
(define S1 (proc->series (lambda(x) 1))) (define S2 (proc->series (lambda(x) (1+ x))))
(define (mul-series s1 s2)
(cons-stream (* (stream-car s1)
(stream-car s2))
(add-series (scale-series (stream-car s1) (stream-cdr s2))
(mul-series (stream-cdr s1) s2))))
Here we check if s1*s1=s2:
(define s3 (mul-series s1 s1)) ;Value: "s3 --> (1 . #[promise 27])" (show-series (subtract-series s3 s2) 6) 0 0 0 0 0 0
What is the coefficient of x^10 in s2*s2?
(series-coeff (mul-series s2 s2) 10) ;Value: 286
(define (invert-unit-series s)
(cons-stream 1 (negate-series (mul-series (stream-cdr s)
(invert-unit-series s)))))
The procedure doesn't go into an infinite loop, because of delayed evaluation.
The idea here is to first divide the denominator series with its leading coefficient, to make it a unit-series, which we can then invert and multiply by the scaled numerator.
(define (div-series s1 s2)
(let ((constant (stream-car s2)))
(if (zero? constant)
'error
(mul-series (scale-series (/ 1 constant) s1)
(invert-unit-series (scale-series (/ 1 constant) s2))))))
(define (integrate-series-tail s)
(define (index-map stream index)
(if (stream-null? stream)
the-empty-stream
(cons-stream (/ (stream-car stream) index) (index-map (stream-cdr stream) (1+ index)))))
(index-map s 1))
Here we integrate s2:
(show-series (integrate-series-tail s2) 10) 1 1 1 1 1 1 1 1 1 ;Value: done
Here's the correct approach:
(define cos-series (cons-stream 1 (negate-series (integrate-series-tail sin-series)))) (define sin-series (cons-stream 0 (integrate-series-tail cos-series)))
this is MUCH nicer than the versions given below, for your curiosity.
The following are NOT correct ways of doing it! I effectively filtered the exp-series:
;; attempt 1
(define (cycle n)
(cond ((= n 1) 2)
((= n 2) 3)
((= n 3) 4)
(else 1)))
(define (cos-series-maker stream)
(define (stream-index-map proc n stream)
(if (stream-null? stream)
the-empty-stream
(cons-stream (proc (stream-car stream) n)
(stream-index-map proc (cycle n) (stream-cdr stream)))))
(define (maker x n)
(cond ((= n 1) x)
((= n 3)(- x))
(else 0)))
(stream-index-map maker 1 stream))
;; attempt 2
(define cos-series (cos-series-maker exp-series))
;; this works as desired but it is not good enough in terms of abstraction.
(define (sin-series-maker stream)
(define (stream-index-map proc n stream)
(if (stream-null? stream)
the-empty-stream
(cons-stream (proc (stream-car stream) n)
(stream-index-map proc (cycle n) (stream-cdr stream)))))
(define (maker x n)
(cond ((= n 2) x)
((= n 4)(- x))
(else 0)))
(stream-index-map maker 1 stream))
(define sin-series (sin-series-maker exp-series))
This is what happens:
(define (integrate-series series constant-term) (cons-stream constant-term (integrate-series-tail series))) ;Value: "integrate-series --> #[compound-procedure 56 integrate-series]" (define exp-series3 (integrate-series exp-series3 1)) ;Unbound variable: exp-series3 ;Type D to debug error, Q to quit back to REP loop:
NOTE! I used exp-series3, because exp-series is already bound in the global environment, and I wouldn't get the desirable behavior/error.
The expression in Exercise 6 uses "cons-stream" which is a special form, which delays the call to exp-series (in this case exp-series3). In the code above, the evaluator first evaluates the argument, exp-series3, and sees that it is unbound.
This is implemented in a very similar way to integrate-series-tail:
(define (deriv-series s)
(define (index-map stream index)
(if (stream-null? stream)
the-empty-stream
(cons-stream (* (stream-car stream) index) (index-map (stream-cdr stream) (1+ index)))))
(index-map (stream-cdr s) 1))
;Value: "deriv-series --> #[compound-procedure 65 deriv-series]"
(show-series integers 5)
1
2
3
4
5
;Value: done
(define deriv-integers
(deriv-series integers))
;Value: "deriv-integers --> (2 . #[promise 66])"
(show-series deriv-integers 5)
2
6
12
20
30
;Value: done
Tan=sin/cos:
(define tan-series (div-series sin-series cos-series)) (show-series tan-series 10) 0 1 0 1/3 0 2/15 0 17/315 0 62/2835 ;Value: done
Sec= 1/cos:
(define sec-series (div-series (coeffs->series '(1)) cos-series)) (show-series sec-series 10) 1 0 1/2 0 5/24 0 61/720 0 277/8064 0 ;Value: done
Now we need to implement xcotx. First I defined (1/x)sinx, and then just divided cosx by it.
(define sin/x-series (stream-cdr sin-series)) (define xcot-series (div-series cos-series sin/x-series)) (show-series xcot-series 5) 1 0 -1/3 0 -1/45 ;Value: done
Here I test d/dx(tan)=?=sec^2
(define test1 (deriv-series tan-series)) ;Value: "test1 --> (1 . #[promise 69])" (define test2 (mul-series sec-series sec-series)) ;Value: "test2 --> (1 . #[promise 70])" (show-series (subtract-series test1 test2) 10) 0 0 0 0 0 0 0 0 0 0 ;Value: done
We need to define factorial first:
(define (fact n)
(define (iter ans togo)
(if (>= 0 togo)
ans
(iter (* ans togo) (- togo 1))))
(iter 1 n))
(define (bernoulli n)
(let ((bern-series (invert-unit-series (stream-cdr exp-series))))
(* (series-coeff bern-series n)
(fact n))))
Now we just generate a table of the first ten non-zero Bernoulli numbers:
B(0)= 1 B(1)=-1/2 B(2)= 1/12 B(4)=-1/720 B(6)= 1/30240 B(8)=-1/1209600 B(10)= 1/47900160 B(12)=-691/1307674368000 B(14)=1/74724249600 B(16)=-3617/10670622842880000(b) Here the answers may vary, but I just tried to automate most of what needed to be done, so I wouldn’t have to type it in over and over.
(define (tan-coef-2n-1 n)
(/ (* (expt -1 (- n 1))
(expt 2 (* 2 n))
(- (expt 2 (* 2 n)) 1)
(bernoulli (* 2 n)))
(fact (* 2 n))))
;Value: "tan-coef-2n-1 --> #[compound-procedure 86 tan-coef-2n-1]"
(define (check-tan-series n)
(series-coeff tan-series (- (* 2 n) 1)))
;Value: "check-tan-series --> #[compound-procedure 88 check-tan-series]"
(define (checker n)
(equal? (tan-coef-2n-1 n) (check-tan-series n)))
;Value: "checker --> #[compound-procedure 91 checker]"
(map checker '(1 2 3 4 5 6 7 8 9 10))
;Value: (#t #t #t #t #t #t #t #t #t #t)
From this we see that the first 10 terms are the same!
Solutions by: George Dolina
Last Modified: Wed Oct 21 11:38:35 EDT 1998