【问题标题】:Implementation of Simpson's Rule (SICP Exercise 1.29)辛普森法则的实施(SICP 练习 1.29)
【发布时间】:2013-10-31 12:44:54
【问题描述】:

以下是我的SICP exercise 1.29 代码。练习要求我们实施 使用高阶过程的辛普森规则sum。应该更多 比原来的integral 程序更准确。但我不知道为什么它不是 我的代码中的情况:

(define (simpson-integral f a b n)
  (define h (/ (- b a) n))
  (define (next x) (+ x (* 2 h)))
  (* (/ h 3) (+ (f a)
                (* 4 (sum f (+ a h) next (- b h)))
                (* 2 (sum f (+ a (* 2 h)) next (- b (* 2 h))))
                (f b))))

我的代码的一些解释:As

h/3 * (y_{0} + 4*y_{1} + 2*y_{2} + 4*y_{3} + 2*y_{4} + ... + 2*y_{n-2} + 4*y_{n-1} + y_{n})

等于

h/3 * (y_{0}
       + 4 * (y_{1} + y_{3} + ... + y_{n-1})
       + 2 * (y_{2} + y_{4} + ... + y_{n-2})
       + y_{n})

我只是使用sum 来计算y_{1} + y_{3} + ... + y_{n-1}y_{2} + y_{4} + ... + y_{n-2}

完整代码在这里:

#lang racket

(define (cube x) (* x x x))

(define (sum term a next b)
  (if (> a b)
      0
      (+ (term a)
         (sum term (next a) next b))))

(define (integral f a b dx)
  (define (add-dx x) (+ x dx))
  (* (sum f (+ a (/ dx 2.0)) add-dx b)
     dx))

(define (simpson-integral f a b n)
  (define h (/ (- b a) n))
  (define (next x) (+ x (* 2 h)))
  (* (/ h 3) (+ (f a)
                (* 4 (sum f (+ a h) next (- b h)))
                (* 2 (sum f (+ a (* 2 h)) next (- b (* 2 h))))
                (f b))))

一些测试(准确的值应该是0.25):

> (integral cube 0 1 0.01)
0.24998750000000042
> (integral cube 0 1 0.001)
0.249999875000001

> (simpson-integral cube 0 1.0 100)
0.23078806666666699
> (simpson-integral cube 0 1.0 1000)
0.24800798800666748
> (simpson-integral cube 0 1.0 10000)
0.2499999999999509

【问题讨论】:

    标签: algorithm lisp scheme racket sicp


    【解决方案1】:

    在您的解决方案中,x 值的计算方式如下:

    h = (b-a)/n
    x1 = a+1
    x3 = x1 +2*h
    x5 = x3 +2*h
    ...
    

    这意味着舍入误差会慢慢累积。 当(b-a)/n 不能表示为浮点数时会发生这种情况。

    如果我们将xi 计算为a+ (i*(b-a))/n,您将获得更准确的结果。

    您的解决方案的此变体使用上述方法计算xi

    (define (simpson-integral3 f a b n)
      (define h (/ (- b a) n))
      (define (next i) (+ i 2))
      (define (f* i) (f (+ a (/ (* i (- b a)) n))))
      (* (/ h 3)
         (+ (f a)
            (* 4 (sum f* 1 next n))
            (* 2 (sum f* 2 next (- n 1)))
            (f b))))
    

    【讨论】:

      【解决方案2】:

      在构造术语方面存在问题,在偶数项(乘以 2)和奇数项(乘以 4)之间交替的方式不正确。我通过向sum 传递一个附加参数来解决这个问题,以跟踪当前术语的偶数或奇数性质,还有其他方法,但这对我有用,并且准确性得到了提高:

      (define (sum term a next b i)
        (if (> a b)
            0
            (+ (term a i)
               (sum term (next a) next b (+ i 1)))))
      
      (define (simpson-integral f a b n)
        (let* ((h (/ (- b a) n))
               (term (lambda (x i)
                       (if (even? i)
                           (* 2.0 (f x))
                           (* 4.0 (f x)))))
               (next (lambda (x) (+ x h))))
          (* (+ (f a)
                (sum term a next b 1)
                (f b))
             (/ h 3.0))))
      
      (simpson-integral cube 0 1 1000)
      => 0.2510004999999994
      

      【讨论】:

      • 谢谢奥斯卡。但是你能告诉我我哪里错了吗?我自己想不通。我添加了一个(simpson-integral cube 0 1.0 10000) 的测试用例,以表明我的代码似乎正在收敛到 0.25。只是没有原来的那么快。
      • @Chenggang 你正在生成两个系列(sum 被调用了两次),而正确的做法是让一个系列具有交替的 4,2 因子
      • 成钢只是重新排列条款。
      猜你喜欢
      • 2018-08-18
      • 2016-01-12
      • 1970-01-01
      • 2021-04-19
      • 1970-01-01
      • 2018-11-01
      • 2020-02-26
      • 2012-10-19
      • 2016-05-05
      相关资源
      最近更新 更多