2013-10-31 3 views
1

다음은 내 코드 SICP exercise 1.29입니다. 이 운동은 심슨의 규칙을 고차 절차 인 sum을 사용하여 구현하도록 요청합니다. 원래 integral 절차보다 정확하게 인 것으로되어 있습니다.심슨 규칙의 구현 (SICP 연습 1.29)

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

내 코드의 일부 설명 :

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 

답변

1

당신의 x 값은 다음과 같이 계산됩니다.

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

이것은 반올림 오류가 천천히 누적됨을 의미합니다. (b-a)/n을 부동 소수점으로 표현할 수없는 경우 발생합니다.

대신 xia+ (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)))) 
1

짝수 항 (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 
+0

Óscar. 하지만 내가 틀린 곳을 말해 줄 수 있니? 나는 나 자신을 이해할 수 없었다. 그리고'(simpson-integral cube 0 1.0 10000)'의 테스트 케이스를 추가하여 코드가 0.25로 수렴하는 것처럼 보입니다. 원래 것만 큼 빨리. –

+0

@Chenggang 당신은 두 가지 계열 ('sum'이 두 번 호출 됨)을 생성하고 있는데, 옳은 것은 4,2 개의 요소가 번갈아 가며 하나의 계열을 가질 때입니다. –

+0

Chenggang이 방금 용어의 순서를 변경하고 있습니다. – soegaard