Вы создаете новую функцию 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)
.
Пока что для теории, но на практике вы можете сделать это только тогда, когда вы можете создавать замыкания, то есть функции с некоторыми данными из их (лексического) окружения для закрытия. (Или если у вас есть способ эмулировать это, например, дополнительный параметр void * user_data
, который используется в некоторых библиотеках C)
Кроме того, поскольку вы пометили это с помощью численного интегрирования, вам необходимо учитывать, что размер шага, используемый integral
, может подходить для многих функций, но размер масштабированного шага может быть слишком большим, чтобы интегрирование давало правильные результаты. Результаты.
Небольшой пример на 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))))))
Вы можете увидеть его в действии, где вывод "Трассировка" показывает, в каких точках оценивается тестовая функция.
А вот версия 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;
}
(в действии)
person
Daniel Jour
schedule
27.01.2016