реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Интеграл, непонятен один момент
Zelepuk
сообщение Dec 14 2012, 08:53
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Хочу найти функцию вычисления определённого интеграла для произвольного массива чисел.
В сети полно примеров взятия интеграла, например:

CODE
double integral(a, b, f, eps)
double a, b; /* концы отрезка */
double eps; /* требуемая точность */
double (*f)(); /* подынтегральная функция */
{
register long i;
double fab = (*f)(a) + (*f)(cool.gif; /* сумма на краях */
double h, h2; /* шаг и удвоенный шаг */
long n, n2; /* число точек разбиения и оно же удвоенное */
double Sodd, Seven; /* сумма значений f в нечетных и в
четных точках */
double S, Sprev;/* значение интеграла на данной
и на предыдущей итерациях */
double x; /* текущая абсцисса */

niter = 0;
n = 10L; /* четное число */
n2 = n * 2;

h = fabs(b - a) / n2; h2 = h * 2.0;

/* Вычисляем первое приближение */
/* Сумма по нечетным точкам: */
for( Sodd = 0.0, x = a+h, i = 0;
i < n;
i++, x += h2 )
Sodd += (*f)(x);

/* Сумма по четным точкам: */
for( Seven = 0.0, x = a+h2, i = 0;
i < n-1;
i++, x += h2 )
Seven += f(x);

/* Предварительное значение интеграла: */
S = h / 3.0 * (fab + 4.0 * Sodd + 2.0 * Seven );
do{
niter++;
Sprev = S;

/* Вычисляем интеграл с половинным шагом */
h2 = h; h /= 2.0;
if( h == 0.0 ) break; /* потеря значимости */
n = n2; n2 *= 2;

Seven = Seven + Sodd;
/* Вычисляем сумму по новым точкам: */
for( Sodd = 0.0, x = a+h, i = 0;
i < n;
i++, x += h2 )
Sodd += (*f)(x);

/* Значение интеграла */
S = h / 3.0 * (fab + 4.0 * Sodd + 2.0 * Seven );

} while( niter < 31 && fabs(S - Sprev) / 15.0 >= eps );
/* Используем условие Рунге для окончания итераций */

return ( 16.0 * S - Sprev ) / 15.0 ;
/* Возвращаем уточненное по Ричардсону значение */
}


Непонятно следущее: f - указывает на подынтегральную функцию. Математически это понятно. Но в Си же это подпрограмма! Я наверное принципиально ен понимаю чего-то но как можно интеграл от подпрограммы взять? или программа должна возвращать указатель на массив?
я же надеялся найти реализацию где в качестве указателя будет указатель на массив, поскольку функция представлена в виде набора отсчётов (массива) от a до b.

Заранее спасибо за разъяснения.

Сообщение отредактировал Zelepuk - Dec 14 2012, 09:38
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Dec 14 2012, 09:44
Сообщение #2


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



double f() - это функция, возвращающая значение в конкретной точке.
Все в соответствии с канонами.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Zelepuk
сообщение Dec 14 2012, 09:52
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Цитата(MrYuran @ Dec 14 2012, 13:44) *
double f() - это функция, возвращающая значение в конкретной точке.
Все в соответствии с канонами.

непонятно как производится "перебор" этих точек. Нужно же посчитать для группы точек. Или в функции f() после каждого вызова должен быть инкремент указателя?
Думаю намного проще было бы сделать что-то вроде цикла где перебирались бы элементы массива.
Я полагаю конструкции вида (*f)(a) можно просто заменить на указатель на массив(с тем же индексом)?

Сообщение отредактировал Zelepuk - Dec 14 2012, 10:02
Go to the top of the page
 
+Quote Post
xemul
сообщение Dec 14 2012, 10:20
Сообщение #4



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Zelepuk @ Dec 14 2012, 13:52) *
непонятно как производится "перебор" этих точек. Нужно же посчитать для группы точек. Или в функции f() после каждого вызова должен быть инкремент указателя?
Думаю намного проще было бы сделать что-то вроде цикла где перебирались бы элементы массива.

Вы в код, Вами же выложенный заглядывали? Там есть кучка обращений (*f)(x), и именно в циклах.
Цитата
Я полагаю конструкции вида (*f)(a) можно просто заменить на указатель на массив(с тем же индексом)?

Ваша задача - нарисовать f(x), т.е. собственно подынтегральную функцию. Будет ли функция представлена аналитически или какой-либо интерполяцией - без разницы, но для любого x на [a, b] она должна вернуть осмысленное значение.
Go to the top of the page
 
+Quote Post
DRUID3
сообщение Dec 14 2012, 10:21
Сообщение #5


山伏
*****

Группа: Свой
Сообщений: 1 827
Регистрация: 3-08-06
Из: Kyyiv
Пользователь №: 19 294



Цитата(Zelepuk @ Dec 14 2012, 11:52) *
Я полагаю конструкции вида (*f)(a) можно просто заменить на указатель на массив...

Ну а если она не массивом задана?

Цитата(Zelepuk @ Dec 14 2012, 11:52) *
(с тем же индексом)?

??


--------------------
Нас помнят пока мы мешаем другим...
//--------------------------------------------------------
Хороший блатной - мертвый...
//--------------------------------------------------------
Нет старик, это те дроиды которых я ищу...
Go to the top of the page
 
+Quote Post
Палыч
сообщение Dec 14 2012, 10:22
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Zelepuk @ Dec 14 2012, 13:52) *
непонятно как производится "перебор" этих точек. Нужно же посчитать для группы точек.

Для этого в программе присутствуют циклы. Аргумент вызываемой функции в каждом цикле увеличивается на величину шага
Код
x += h2

затем вычисляется значение функции в точке х и вычисляется сумма значений
Код
S... += (*f)(х)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 14 2012, 11:24
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Zelepuk @ Dec 14 2012, 12:53) *
Хочу найти функцию вычисления определённого интеграла для произвольного массива чисел.
Может я чего-то не понимаю?
В чём смысл (достоинство) приведенного вами кода для дискретной функции?
Для массива чисел очень просто найти площадь под графиком (интеграл) просто просуммировав площади между соседними точками (можно методом прямоугольников - очень быстро, а можно трапецией - чуть медленнее но чуть точнее).


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
DRUID3
сообщение Dec 14 2012, 11:35
Сообщение #8


山伏
*****

Группа: Свой
Сообщений: 1 827
Регистрация: 3-08-06
Из: Kyyiv
Пользователь №: 19 294



Цитата(demiurg_spb @ Dec 14 2012, 13:24) *
Может я чего-то не понимаю?
В чём смысл (достоинство) приведенного вами кода для дискретной функции?

Точность... Ошибка вычисления... Функция на входе то ожидается аналитическая.


--------------------
Нас помнят пока мы мешаем другим...
//--------------------------------------------------------
Хороший блатной - мертвый...
//--------------------------------------------------------
Нет старик, это те дроиды которых я ищу...
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 14 2012, 11:42
Сообщение #9


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(DRUID3 @ Dec 14 2012, 15:35) *
Точность... Ошибка вычисления... Функция на входе то ожидается аналитическая.
Это-то понятно, но у него не аналитическая функция, а массив. И мне думается что этот алгоритм вообще не применим для его случая.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Xenia
сообщение Dec 14 2012, 11:51
Сообщение #10


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(demiurg_spb @ Dec 14 2012, 15:24) *
Для массива чисел очень просто найти площадь под графиком (интеграл) просто просуммировав площади между соседними точками (можно методом прямоугольников - очень быстро, а можно трапецией - чуть медленнее но чуть точнее).


Интересно, откуда всякий раз выползает предубеждение, что метод прямого суммирования дискрет менее точен, чем сумма трапеций, а последний более трудоёмок?

Ведь если точки идут по сетке через равные интервалы, то площадь отдельной трапеции равна полусумме соседних отсчетов (Fi-1 + Fi)/2 или (что тоже самое!) сумме половинок Fi-1/2 + Fi/2. Но когда начнём все эти трапеции друг с дружкой складывать, то соседние половинки объединятся в целое! В результате чего получится простая сумма дискрет.

Впрочем, небольшая разница тут всё же есть - на самых краях, там, где половинок не хватает. Поэтому метод трапеций отличается от метода прямого суммирования только величиной (F0 + Fn)/2, где F0 - начальная точка, а Fn - конечная. Разница в трудоёмкости, как видим, здесь совершенно ничтожна. А те, у кого она велика, занимаются избыточным суммированием и дележкой на 2 на каждом обороте цикла.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 14 2012, 11:58
Сообщение #11


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Xenia @ Dec 14 2012, 15:51) *
Так я прямо и написал об этом что чуть лучше и чуть трудозатратнее. Никакого заблуждения как и предубеждения нет:-)

Цитата(Xenia @ Dec 14 2012, 15:51) *
Разница в трудоёмкости, как видим, здесь совершенно ничтожна.
Всё от задачи зависит. Вот если массив даблов да ещё и на 8-ми битнике.... я бы разницу точно ощутилsm.gif


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
_Ivana
сообщение Dec 14 2012, 12:10
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 13-08-11
Из: Воронеж
Пользователь №: 66 710



Не, ну можно поискать приключений, вылить воду и свести к предыдущей задаче. Проинтерполировать на каждом интервале многочленом n-й степени и брать интеграл на нем, рассчитывая разность первообразных по формуле Ньютона-Лейбница sm.gif
Go to the top of the page
 
+Quote Post
Xenia
сообщение Dec 14 2012, 12:38
Сообщение #13


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(_Ivana @ Dec 14 2012, 16:10) *
Не, ну можно поискать приключений, вылить воду и свести к предыдущей задаче. Проинтерполировать на каждом интервале многочленом n-й степени и брать интеграл на нем, рассчитывая разность первообразных по формуле Ньютона-Лейбница sm.gif


Тогда demiurg_spb на своём 8-битнике просто зашьётся. sm.gif
Go to the top of the page
 
+Quote Post
_Ivana
сообщение Dec 14 2012, 12:56
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 13-08-11
Из: Воронеж
Пользователь №: 66 710



А кто его знает, с какой частотой у автора идут отсчеты его функции? Он об этом скромно умолчал. Может она близка к частоте Найквиста (при условии ограниченности спектра функции) и остается только использовать суровые методы аппроксимации между отсчетами sm.gif Кстати, если "произвольные отсчеты" идут ещё реже, то задача становится ещё интереснее. Или, если у него отсчеты какой-нибудь функции Дирихле, к примеру sm.gif
Go to the top of the page
 
+Quote Post
Xenia
сообщение Dec 14 2012, 13:13
Сообщение #15


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



А кстати, а чего это народ функцию от указателя так вычурно вычисляет?
S += (*f)(х);
На мой взгляд (а мои взгляды могут расходиться со взглядами компилятора sm.gif), такую функцию следует вызывать как обычную
S += f(х);
Тем более что прецедент уже есть - существует два разных способа объявления массива:
int array[100], *parray=array;
И тем не менее, обоими массивами пользуются одинаково, когда достают из них элементы:
S += array[x];
или
S += parray[x];
а вовсе не (*parray)[x];
И все только потому, что array - тоже указатель, только константный. А, значит, и оператор [] будет их разыменовывать правильно в обоих случаях.

По аналогии с этим, и функцию по указателю можно вызывать напрямую, как f(x), поскольку обычная функция (не указатель) тоже является указателем на функцию, только константным. Значит, и оператор () тоже должен работать в обоих случаях одинаково.
Или я не права?
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 03:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.02816 секунд с 7
ELECTRONIX ©2004-2016