使用计算 f 在 [0,1] 上的积分的函数 integral( f ) 来计算 f 在任何区间上的积分
Use a function integral( f ) which computes the integral of f over [0,1] to compute the integral of f over any interval
如何使用计算函数 f 在 [0,1] 上的积分的(假设的)例程 integral( f ) 来计算 f 在任何区间 [a,b] 上的积分?
如果我想更改积分区间,我会使用以下替换:
y = (x-a)/(b-a)
dy = (1/(b-a))dx
这意味着我现在可以计算 [0,1] 上的积分 f(y)*(b-a)dy 以获得与 [a,b] 上积分 f(x)dx 相同的结果,但是函数 integral() 接受一个参数 - 一个函数 - 我很难弄清楚如何使用我发现的替换来导出该函数。
您创建了一个新函数 g
,它是原始函数 f
的适当缩放版本。
g(x) = f(a + x * (b - a))
// Now we have ...
// g(0) = f(a)
// g(1) = f(b)
// ... and the function between is linearly scaled
然后你把这个函数传给integral
。结果需要按 (b - a)
.
缩放(因为步骤也已缩放)
理论到此为止,但在实践中,您只能在可以创建闭包时执行此操作,即使用来自其(词法)环境的一些数据来关闭的函数。 (或者,如果您有某种方法可以模拟它,例如某些 C 库中使用的附加 void * user_data
参数)
此外,由于您用 numerical-integration 标记了它,您需要考虑 integral
使用的步长可能适用于许多功能,但 scaled 步长可能太大,无法通过积分产生正确的结果。
Common Lisp 中的小例子:
;; from http://rosettacode.org/wiki/Numerical_integration#Common_Lisp
(defun left-rectangle (f a b n &aux (d (/ (- b a) n)))
(* d (loop for x from a below b by d summing (funcall f x))))
(defun integral (f)
(left-rectangle f 0 1 10))
(defun integral-range (f a b)
(* (- b a) (integral #'(lambda (x) (funcall f (float (+ a (* x (- b a)))))))))
(defun test-fn (x) (* x 2))
(trace test-fn)
(let ((i (integral-range #'test-fn 3 9)))
(format t "Result of numerical integration: ~a~%" i)
(format t "Error of numerical integration: ~a~%" (abs (- i (- (* 9 9) (* 3 3))))))
You can see it in action,其中 "Trace" 输出显示评估测试函数的点。
这里是 C 版本,通过分配全局静态变量来模拟上述闭包:
#include <stdio.h>
#include <math.h>
// from http://rosettacode.org/wiki/Numerical_integration#C
double int_leftrect(double from, double to, double n, double (*func)())
{
double h = (to-from)/n;
double sum = 0.0, x;
for(x=from; x <= (to-h); x += h)
sum += func(x);
return h*sum;
}
double integral(double (*func)()) {
return int_leftrect(0, 1, 10, func);
}
static double from;
static double to;
static double (*fn)();
double scaled(double x) {
return fn(from + x * (to - from));
}
double integral_range(double (*func)(), double a, double b) {
from = a;
to = b;
fn = func;
return integral(scaled) * (b - a);
}
double test_fn(double x) {
double result = 2 * x;
printf("TRACE: test_fn(%f) => %f\n", x, result);
return result;
}
int main(void) {
double result = integral_range(test_fn, 3, 9);
double expected = (9 * 9) - (3 * 3);
printf("result of numerical integration: %f\n", result);
printf("error of numerical integration: %f\n", fabs(result - expected));
return 0;
}
如何使用计算函数 f 在 [0,1] 上的积分的(假设的)例程 integral( f ) 来计算 f 在任何区间 [a,b] 上的积分?
如果我想更改积分区间,我会使用以下替换:
y = (x-a)/(b-a)
dy = (1/(b-a))dx
这意味着我现在可以计算 [0,1] 上的积分 f(y)*(b-a)dy 以获得与 [a,b] 上积分 f(x)dx 相同的结果,但是函数 integral() 接受一个参数 - 一个函数 - 我很难弄清楚如何使用我发现的替换来导出该函数。
您创建了一个新函数 g
,它是原始函数 f
的适当缩放版本。
g(x) = f(a + x * (b - a))
// Now we have ...
// g(0) = f(a)
// g(1) = f(b)
// ... and the function between is linearly scaled
然后你把这个函数传给integral
。结果需要按 (b - a)
.
理论到此为止,但在实践中,您只能在可以创建闭包时执行此操作,即使用来自其(词法)环境的一些数据来关闭的函数。 (或者,如果您有某种方法可以模拟它,例如某些 C 库中使用的附加 void * user_data
参数)
此外,由于您用 numerical-integration 标记了它,您需要考虑 integral
使用的步长可能适用于许多功能,但 scaled 步长可能太大,无法通过积分产生正确的结果。
Common Lisp 中的小例子:
;; from http://rosettacode.org/wiki/Numerical_integration#Common_Lisp
(defun left-rectangle (f a b n &aux (d (/ (- b a) n)))
(* d (loop for x from a below b by d summing (funcall f x))))
(defun integral (f)
(left-rectangle f 0 1 10))
(defun integral-range (f a b)
(* (- b a) (integral #'(lambda (x) (funcall f (float (+ a (* x (- b a)))))))))
(defun test-fn (x) (* x 2))
(trace test-fn)
(let ((i (integral-range #'test-fn 3 9)))
(format t "Result of numerical integration: ~a~%" i)
(format t "Error of numerical integration: ~a~%" (abs (- i (- (* 9 9) (* 3 3))))))
You can see it in action,其中 "Trace" 输出显示评估测试函数的点。
这里是 C 版本,通过分配全局静态变量来模拟上述闭包:
#include <stdio.h>
#include <math.h>
// from http://rosettacode.org/wiki/Numerical_integration#C
double int_leftrect(double from, double to, double n, double (*func)())
{
double h = (to-from)/n;
double sum = 0.0, x;
for(x=from; x <= (to-h); x += h)
sum += func(x);
return h*sum;
}
double integral(double (*func)()) {
return int_leftrect(0, 1, 10, func);
}
static double from;
static double to;
static double (*fn)();
double scaled(double x) {
return fn(from + x * (to - from));
}
double integral_range(double (*func)(), double a, double b) {
from = a;
to = b;
fn = func;
return integral(scaled) * (b - a);
}
double test_fn(double x) {
double result = 2 * x;
printf("TRACE: test_fn(%f) => %f\n", x, result);
return result;
}
int main(void) {
double result = integral_range(test_fn, 3, 9);
double expected = (9 * 9) - (3 * 3);
printf("result of numerical integration: %f\n", result);
printf("error of numerical integration: %f\n", fabs(result - expected));
return 0;
}