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

 
 
> Интеграл, непонятен один момент
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
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 17)
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
demiurg_spb
сообщение Dec 14 2012, 13:39
Сообщение #16


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

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



Цитата(Xenia @ Dec 14 2012, 17:13) *
Или я не права?
не совсем. попробуйте двумерный массив.
Ну или посмотрите что вам вернёт sizeof(array1) и что sizeof(array2) для таких вот случаев
Код
uint8_t array1[10];
uint8_t array2[2][5];


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


Гуру
******

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



Цитата(demiurg_spb @ Dec 14 2012, 17:39) *
не совсем. попробуйте двумерный массив.
Ну или посмотрите что вам вернёт sizeof(array1) и что sizeof(array2) для таких вот случаев
Код
uint8_t array1[10];
uint8_t array2[2][5];


Ну так я же не просила вас вызывать двухмерную функцию. sm.gif
Речь шла о том, что оператор [] приложим к указателю, так же как и оператор (). Оба они требуют, чтобы слева от них стоял указатель, хоть бы и вычисляемый. Т.е. я не за идентичность указателей ратовала, а за единообразие выполнения операторов "скобочки". А именно, в выражении f() скобочки должны интерпретировать f, как указатель (в данном случае на функцию), а не как-то иначе. Зачем же тогда f предварительно разыновывать? Ведь если имя массива (без скобочек) это указатель, то и имя фукции без скобочек тоже должно быть указателем. А чем же ещё-то?
Go to the top of the page
 
+Quote Post
ReAl
сообщение Dec 14 2012, 17:09
Сообщение #18


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Xenia @ Dec 14 2012, 15:45) *
А именно, в выражении f() скобочки должны интерпретировать f, как указатель (в данном случае на функцию), а не как-то иначе.
И это так и есть по стандарту.
Цитата
6.3.2 Other operands
6.3.2.1 Lvalues, arrays, and function designators

...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.

4 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.

Цитата(Xenia @ Dec 14 2012, 15:45) *
Зачем же тогда f предварительно разыновывать?
Абсолютно незачем. Так как после этого разименованное ‘‘function returning type’’ моментально опять превращается в ‘‘pointer to function returning type’’ для того, чтобы скобочки () (которые в данном случае являются «function-call operator») могли этим воспользоваться.
Цитата
6.5.2.2 Function calls
Constraints
1
The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.

Как следствие, разыменовывать можно сколько угодно раз, это ничего не меняет.
Код
#include <stdio.h>

int (*pf)(const char *) = puts;

int main()
{
        pf("pf");
        // Разыменовываем, автоматически приводится к указателю, мы его опять разыменовываем и т.д.
        (****pf)("****pf");
        return 0;
}

С выборкой указателя на функцию из массива аналогично pfunc_array[index](arguments); и всё.
Но при большом желании можно и (*****pfunc_array[index])(arguments);. Эффект тот же.

И где-то на этом форуме об этом уже говорили. И вроде как не раз.

_____________________
Сегодня смотрел «День сурка». Опять…


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

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

 


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


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