Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
933 Кб
Скачать
☆

Передача функций

В этом разделе рассмотрим передачу в качестве аргумента имени функции.

Этот специфический вид аргумента позволяет придать программе универсальность.

Пример. Найти y=min(f(x)), где {xi}, i=1...n. Существует множество методов нахождения экстремума функции многих переменных, практически не зависящих от вида функции, минимум которой отыскивается.

Сопряжение, т.е. имя функции со списком аргументов, min_fun(n, x, dx, eps, f) практически одинаково для различных методов. Здесь: n – число переменных; вектор (одномерный массив) x является одновременно и входным параметром (начальное приближение), и выходным (найденная точка минимума); dx – начальный шаг поиска; eps – точность нахождения минимума; f – имя (язык С) или адрес (язык Basic) минимизируемой функции .

C Передаваемое значение является адресом функции. Следовательно, соответствующий параметр – указатель на функцию. Это специфический объект, характерный только для языков C и С++.

Формат объявления: [<тип>](*<имя>)( );

Чтобы при вызове в вызывающей процедуре имя функции-аргумента не рассматривалось бы транслятором как простая переменная, необходимо в ней объявить прототип минимизируемой функции и самой процедуры минимизации:

float f1(int, float [ ]), // Минимизируемая функция

min_fun(int, float [ ], float, float, float(*)( )) // Процедура минимизации

z;

..........................

z=min_fun(l, s, delta_x, epsilon, f1); // Обращение к процедуре

Вызываемая процедура:

float min_fun(int n, // Число измерений

float x[ ], // Начальное приближение

//Результат: точка минимума

float dx, // Начальный шаг поиска

float eps, // Заданная точность нахождения минимума

float(*f)( )){// Адрес минимизируемой функции

..........................

}

Следует различать записи:

<тип> *f( ); и <тип>(*f)( );

П ервая – прототип функции без параметров, возвращающей указатель на <тип>, вторая – прототип указателя на функцию, возвращающей значение данного типа.

Пример. Вычислить и напечатать таблицу функции:

Интеграл вычислять методом трапеций.

/* Вычислить таблицу y=f(alfa) */

int main( ){

double f1(double), // Подинтегральная функция

y, // Значение интеграла

alfa, // Параметр

trap(double, double, int, double(*)(double ));// Метод трапеций

for(alfa=2; alfa<3.05; alfa+=.1){

y=trap(.15, alfa, 20, f1);

printf("%10cальфа=%.1lf интеграл=%.6lf\n", ' ', alfa, y);

}

} // End main

/* Интегрирование методом трапеций */

double trap( double a, // Нижний предел интегрирования

double b, // Верхний --------------------

int k, // Число элементарных интервалов

double (*f)(double )){// Подинтегральная функция

double dx, // Размер элементарного интервала

t;

int i;

dx=(b-a )/k;

t=((*f)(a)+(*f)(b))/2;

for(i=1; i<k; i++){

t += (*f)(a+i*dx);

}

return dx*t;

} // End trap

/* Подинтегральная функция */

double f1(double x){

return exp(x)*cos(pow(x, 3));

} // End f1

Basic

Поскольку в этом языке нет типа данных указатель, для приведенных выше и некоторых других целей введен тип данных делегат и соответствующее ключевое слово Delegate. Данные этого типа объявляются на уровне модуля вне процедур как новый тип данных, доступный всем модулям программы..

Формат объявления:

Delegate {Function | Sub} <имя> ([<список параметров>]) [As <тип>]

Для подпрограммы тип возвращаемого значения отсутствует.

В вызывающей процедуре, передающей адрес процедуры в качестве аргумента, должна объявляться переменная типа, совпадающего с именем делегата, которой задается адрес нужной процедуры и имя которой передается в качестве аргумента.

Ниже приводится решение предыдущей задачи на языке Basic.

Module Main

‘ Объявление делегата

Delegate Function UndInteg(ByVal x As Double) As Double

Sub Main()

Dim y As Double ' Значение интеграла

Dim alfa As Double ' Параметр

Dim DelF1 As UndInteg ' Переменная типа делегата

DelF1 = AddressOf F1 ' Задание адреса функции-аргумента

For alfa = 2 To 3.05 Step 0.1

y = Integr(0.15, alfa, 20, DelF1)

Console.WriteLine("альфа={0:f1} интеграл={1:f4}", alfa, y)

Next

Console.ReadLine()

End Sub

End Module

Module Integ

' Интегрирование методом трапеций

' a-нижний предел, b-верхний предел, k-число элем.интервалов, F1-адрес

‘ подинтегральной функции

Function Integr(ByVal a As Double, ByVal b As Double, _

ByVal k As Short, ByRef F As UndInteg)

Dim dx As Double 'Размер элементарного интервала

dx = (b - a) / k

Integr = (F(a) + F(b)) / 2

For i As Integer = 1 To k - 1

Integr += F(a + i * dx)

Next

Return Integr *dx

End Function

End Module

Imports System.Math

Module UnderInteg

' Подинтегральная функция

Function F1(ByVal x As Double) As Double

F1 = Exp(x) * Cos(x^3))

End Function

End Module

Совет. Сравните реализации, найдите отличия, запомните и решите задачу ВЦ 24 с использованием делегата.