【问题标题】:SICP exercise 3.62SICP 练习 3.62
【发布时间】:2015-08-25 01:18:47
【问题描述】:

我已经完成了练习 3.59, 3.60, 3.61 并且卡在了 3.62,所以我转向 sicp-solutions@scheme wiki community 寻求帮助。

练习 3.59 和 3.60 可以使用 sinecosine 案例轻松测试,但不是 3.61 或 3.62。

社区提供的3.62代码在sinecosine系列正确的情况下产生全零tangent系列:

> (display-stream-until sine-series 7)
0
1
0
-1/6
0
1/120
0

> (display-stream-until cosine-series 7)
1
0
-1/2
0
1/24
0
-1/720

> (display-stream-until tangent-series 7)
0
0
0
0
0
0
0

一开始我认为我之前练习中写的代码可能是错误的,所以我在社区中检查了我的 3.59/3.60/3.61 的解决方案,结果发现我们产生了相同的结果。

我尝试将3.59/3.60/3.61 的代码复制到我的IDE(DrRacket) 中,但tangent 系列仍然打印为零。

代码如下:

(define (mul-series s1 s2)
  (cons-stream (* (stream-car s1)
                  (stream-car s2))
               (add-streams (mul-streams (stream-cdr s1)
                                         (stream-cdr s2))
                            (mul-series s1 s2))))

(define (reciprocal-series s)
  (cons-stream 1
               (scale-stream (mul-series (stream-cdr s)
                                         (reciprocal-series s))
                             -1)))

(define (div-series s1 s2)
  (let ((c (stream-car s2)))
    (if (= c 0)
        (error "constant term of s2 can't be 0!")
        (scale-stream
         (mul-series s1
                     (reciprocal-series (scale-stream s2
                     (/ 1 c))))
     (/ 1 c)))))

(define tangent-series
  (div-series sine-series
              cosine-series))

及其需要的部分:(太长无法用正文突出显示)

(require (only-in "myLib.rkt"
                  cons-stream
                  stream-car
                  stream-cdr
                  add-streams
                  mul-streams
                  scale-stream
                  stream-map
                  ones
                  integers
                  sine-series
                  cosine-series
                  stream-ref
                  display-stream-until))

谁能告诉我我的代码有什么问题或者可能的错误隐藏在哪里?

顺便问一下,你们如何在 SICP 上验证您的代码?

我发现几个博客/github 存储库提供的代码没有(足够)测试用例。

我很难用纯代码处理这些数学问题。

【问题讨论】:

    标签: scheme sicp


    【解决方案1】:

    问题在于mul-series
    系列 [a0 + a1x + ...] 与系列 [b0 + b1 的乘积x + ...] 是
    [a0b0 + (a0b1 + a1b 0)x + ...]
    但是你的mul-series 产生
    (cons-stream a0b0 (add-streams (mul-streams (cdr s1) (cdr s2)) (mul-series s1 s2)))
    = (cons-stream a0b0 (add-streams [a1b1, ... ] [a0b0, ...]))
    = [a0b0, a1b1 + a0b 0, ...]

    您可以使用恒等式 sin(x)2 + cos(x)2 = 1 检查mul-series(如练习 3.60 中所建议的那样)。
    其他一些可以尝试的简单测试用例是
    [2] * [0 + x] = [0 + 2x]
    [1 + x] * [1 + x] = [ 1 + 2x + 1x2]

    使用适当的辅助函数,您的测试可能如下所示:

    > (show-series (add-streams (mul-series sine-series sine-series) (mul-series cosine-series cosine-series)))
    1 + 0*x + 0*x^2 + ...
    > (show-series (mul-series (make-series '(2)) (make-series '(0 1))))
    0 + 2*x + ...
    > (show-series (mul-series (make-series '(1 1)) (make-series '(1 1))))
    1 + 2*x + 1*x^2 + ...
    

    这是我定义的辅助函数:

    (define zeroes (cons-stream 0 zeroes))
    
    ;; make-series takes a list of numbers and returns an infinite stream
    ;; with those numbers followed by 0's
    (define (make-series coeffs)
      (if (null? coeffs)
          zeroes
          (cons-stream (car coeffs) (make-series (cdr coeffs)))))
    
    ;; show-stream prints the first 10 items in a stream
    (define (show-stream stream)
      (begin (show-stream-helper stream 10)))
    
    (define (show-stream-helper stream n)
      (if (= 0 n)
          (begin (display "...")
                 (newline))
          (begin (display (stream-car stream))
                 (display ", ")
                 (show-stream-helper (stream-cdr stream) (- n 1)))))
    
    ;; show-series is like show-stream, but uses the format a0 + a1*x + ...
    (define (show-series stream)
      (show-series-helper stream 0 10))
    
    (define (show-series-helper stream n m)
      (if (> n m)
          (begin (display "...")
                 (newline))
          (begin (show-monomial (stream-car stream) n)
                 (display " + ")
                 (show-series-helper (stream-cdr stream) (+ 1 n) m))))
    
    ;; show-monomial displays a*x^n
    (define (show-monomial coeff pow)
      (cond
       ((= 0 pow)
        (display coeff))
       ((= 1 pow)
        (display coeff)
        (display "*x"))
       (else
        (display coeff)
        (display "*x^")
        (display pow))))
    

    【讨论】:

    • 我对您的代码感到困惑:(mul-series sine-series sine-series),您是否遗漏了x 部分(x、x^2、x^3 ...)?
    • sine-series 是一个带有数字 [0, 1, 0, -1/6, ...] 的流,代表幂级数 [0 + 1*x + 0*x^2 + (-1/6)*x^3 + ...]。 x 是隐含的。 (mul-series sine-series sine-series) 的结果是具有 sin(x)^2 幂级数系数的流。可以证明 sin(x)^2 = x^2 + (-1/3)*x^4 + (2/45)*x^6 + ... 所以(mul-series sine-series sine-series) 返回流 [0, 0, 1, 0, -1/3, 0, 2/45, ...]。
    • 我的辅助函数show-seriesdisplay-stream 类似,不同之处在于它将所有内容打印在一行上,并使用*x^n 提醒我们流中的每个数字代表幂级数中的一个系数。
    • 我想我把 mul-streamsmul-series 搞砸了
    猜你喜欢
    • 2012-07-05
    • 2011-11-05
    • 2017-02-03
    • 2010-12-26
    • 2012-12-15
    • 2021-05-23
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    相关资源
    最近更新 更多