用黎曼积分公式计算高阶函数

时间:2019-12-29 01:54:03

标签: scheme elisp sicp

SICP在1.3.1章中介绍了黎曼积分公式

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

将其应用于特定情况

#+name: case-1.3.1-integral.scm
#+BEGIN_SRC scheme :session sicp
(define pi 3.141592653589793)

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

(define (f b)
  (lambda (x) (/ 1 (sqrt
                    (- (sin x)
                       (sin b))))))


(* (integral2 f 0 (/ pi 6) 0.00001)
   (sqrt (/ 40
            (* 3 9.8))))
#+END_SRC

#+RESULTS: case-1.3.1-integral.scm
: 0.0-1.777598336021436i

得到了一个完美的答案1.777598336021436

然后将其翻译为elisp

从小开始:

#+name: case-1.3.1-integral.el
#+begin_src emacs-lisp :session sicp :lexical t
(defun integral (f a b dx)
  (* (sum f
     (+ a (/ dx 2.0))
     (lambda (x) (+ x dx))
     b)
     dx))

(defun sum(term a next b)
  (if (> a b)
      0
    (+ (funcall term a)
       (sum term (funcall next a) next b))))

(integral #'cube 0 1 0.01)
#+end_src

#+RESULTS: case-1.3.1-integral.el
: 0.24998750000000042

它可以工作,因此可以用来解决先前的问题

#+begin_src emacs-lisp :session sicp :lexical t 
(defvar pi 3.141592653589793)

(defun integral (f a b dx)
  (* (sum f
     (+ a (/ dx 2.0))
     (lambda (x) (+ x dx))
     b)
     dx))

(defun f (b)
  (lambda (x) (/ 1 (sqrt
                    (- (sin x)
                       (sin b))))))

(defun integral2 (f a b dx)
  (* (sum (funcall f b)
          (+ a (/ dx 2.0))
          (lambda (x) (+ x dx))
          b)
      dx))

(integral2 #'f 0 (/ pi 6) 0.01)

#+end_src

但是它返回了毫无意义的结果

ELISP> (integral2 #'f 0 (/ pi 6) 0.01)
-0.0e+NaN

出什么问题了?

1 个答案:

答案 0 :(得分:1)

使用Scheme时获得的答案是一个复数,即调用sqrt的结果(您首先确定Scheme代码正确吗?应仔细检查):

0.0-1.777598336021436i

不幸的是,Elisp doesn't support复数,这就是为什么我们在那里得到NaN的原因。但这不是真正的问题。您应该调查为什么在Scheme代码中得到复杂的结果,整数不应该返回复杂的值!