Нахождение экстремума функции Методом Золотого Сечения.

Условие:
Вычислить экстремум функции y(x)=x+lg(1/x); с заданной точностью ε,
т.е. найти координаты (xe, ye).

Значение границ интервала, начальное значение шага и точность ввести с клавиатуры в главной программе. Координаты экстремума, конечное значение шага и количество разбиений вывести на экран в главной программе.

Решение:

В программе есть смысл оформить следующие подпрограммы:

  1. Процедура ExtremGC, вычисляющая экстремум с заданной точностью (будет вызываться из главной программы)

    Входные параметры:
    • границы интервала [a, b]
    • начальное значение шага dx
    • точность ε


    Выходные:
    • координаты (xe, ye) экстремума
    • конечное значение шага dx
    • количество разбиений n
  2. Функции dannFunc, вычисляющая значение y(x) (будет вызываться из процедура ExtremGC) и позволяющая в будущем достаточно легко адаптировать код программы под новые функции.
Метод золотого сечения для определения экстремума функции
На Pascal для функции y(x)=x+lg(1/x); это будет выглядеть так:

function dannFunc (x: real): real;
begin
    if x<=0 then writeln('недопустимое значение аргумента - ',x);
    dannFunc:= x+ln(1/x)/ln(10); {перевод десятичного логарифм в натуральный}
end;

Первая строка проверяет входной параметр на допустимость (индивидуально для конкретной функции) и выдает соответствующее сообщение.
Вторая строка возвращает вычисленное значение функции.
Так как в Pascal отсутствует функция десятичного логарифма, но есть натурального, то воспользовался формулой lgA = lnA / ln10;

Далее...

{Нахождение экстремума функции на отрезке. Метод золотого сечения}
procedure ExtremGC (a, b, eps: real;
                   var xe, ye, dx1: real;
                   var nn: longint);
var x1, x2, zc, y1, y2 :real;
begin
    nn:= 0;
    zc:=(1+sqrt(5))/2; {~1.618 -константа золотого сечения}
    { writeln; writeln(zc); {можно убрать знак комментария для проверки}

    while (b-a>eps) do
    begin
       x1:=b-((b-a)/zc); x2:=a+((b-a)/zc);
       y1:= dannFunc(x1); y2:= dannFunc(x2);
       if y1>=y2 then a:=x1 else b:=x2; {поиск минимума}
       {if y1<=y2 then a:=x1 else b:=x2; {поиск максимума,}
       { возможно, понадобится для другой функции}
       inc(nn); { количество разбиений }
    end;

dx1:= abs(b-a); { конечное значение шага }
xe:=(a+b)/2; ye:= dannFunc (xe); { результат: координаты точки экстремума }

end;

Данная процедура получает семь параметров. Первые три параметра передаются по значению, а следующие четыре - по ссылке.

Рассчитываем переменную zc:=(1+sqrt(5))/2; .
По идее – это константа, так как все данные в формуле известны и не зависят от параметров, но оформить ее как константу нельзя, потому что используется функция извлечения квадратного корня.

Цикл while(b-a>eps) do сознательно не оптимизирован… Конечно, метод золотого сечения позволяет (т.е. достаточно) считать функцию только в одной новой точке, а не в двух (при каждой итерации как сделано в моем примере), но для учебной задачи, где заданная функция достаточно проста и машинное время на ее выполнение не критично, это вполне допустимо (если, конечно, Ваш преподаватель не акцентировал на этом моменте особое внимание).

Суть метода (цикла): имеющийся отрезок [a,b] делится точками х1 и х2 где a<x1<x2<b в пропорциях золотого сечения. В этих точках определяется значение функции. После этого не интересующий программу отрезок отбрасывается, а оставшийся (если не достигнута заданная точность) подвергается той же обработке на следующем шаге цикла. Цикл закончится только тогда, когда рассматриваемый отрезок сузится до размеров ε. За ответ будет принята середина этого крохотного отрезка.

Если входные параметры для данного примера   a=0.1,    b=1, то
при первой итерации х1=0.4438(z2),    х2=0.6562(z3)
при второй итерации a=0.1,    b=0.6562(z3),    х1=0.3124(z1),    х2=0.4438(z2)
при третьей итерации a=0.3124(z1),    b=0.6562(z3),    х1=0.4438(z2),    х2=0.5249
…и так попеременно отбрасывая правые или левые части алгоритм неминуемо достигнет точки экстремума.

По окончанию цикла, остается инициализировать три параметра (переменные) по ссылке (т.к. параметр nn уже инициализирован в ходе цикла).

Все.
Для окончательного решения задачи остается написать главную программу из четырех строк.

  1. Приглашение (типа… write('Ведите a, b, eps ->');)
  2. Инициализация переменных с клавиатуры ( readln(a, b, eps); )
  3. Вызов процедуры ExtrеmGC(a, b, eps, xe, ye, dx1, n);
  4. Вывод на экран переменных xe, ye, dx1, n (в удовлетворяющем Ваш вкус виде), которые получили инициализацию в ExtrеmGC.

скачать ехе-файл для тестирования

скачать pas-файл кода в виде зашифрованного архива (пароль для подписчиков в рассылке)

Заданная функция в моем примере y(x)=x+lg(1/x); имеет два максимума в точках +0 и +∞ и один минимум в точке ~0,4343. Значение функции в точке экстремума y(0,4343)= ~0,7965



Можно и на другие языки переписать...


К слову, здесь        Метод золотого сечения на VBA (Excel 2007)

Другие примеры на языке «Delphi»

Другие примеры на языках «Pascal», «PascalABC»




Поделиться в соц сетях:




Если на этой странице не нашлось того, что Вы так искали...

         Не расстраивайтесь, не все потеряно... Смело щелкайте...

исходный код на заказ. orenstudent.ru Автоматизация документов MS Office. orenstudent.ru исходный код на заказ. orenstudent.ru Помогите найти и устранить ошибку в исходном коде программы. orenstudent.ru Skype-консультирование по программированию
Скайп-консультации

Акция !!!
исходный код комментарии цена минимальная


требуются
школьники!


и СТУДЕНТЫ!
Кому не плевать
на деньги!
Сайт помощи студентам по программированию и информатике

Program code