Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2012 Вычислительная математика практика 01-03.pdf
Скачиваний:
16
Добавлен:
05.06.2015
Размер:
390.2 Кб
Скачать

Практическое задание №1. Метод половинного деления

Краткое описание задания: задана решаемая функция вида f(x) = 0. Методом деления отрезка пополам найти её решение с заданной точностью ε.

Методические указания

1.Программа ничего не принимает с клавиатуры. Все исходные данные задаются в коде программы, как правило, в основном модуле, во время вызова функции метода (внутри функции main).

2.Программа решает задачу двумя способами в двух функциях метода: а) вычислительный цикл завершается, когда будет достигнута заданная

точность вычисления.

б) число циклов рассчитывается перед вычислительным циклом, исходя из заданной точности;

3.Название модуля (файла типа .h) для функции метода mhalfint.

4.Название функции метода halfint.

5.Сигнатура (прототип) функции метода имеет следующий вид:

double halfintN(pef ef, double X1, double X2, double eps, int* success);

Здесь:

-N — цифра 1 или 2 для первого и второго способов решения;

-pef — тип решаемой функции;

-X1 — левая граница начального отрезка;

-X2 — правая граница начального отрезка;

-eps — заданная точность решения;

-success — возвращаемый признак успешного выполнения алгоритма.

-возвращаемое значение функции метода — результат вычисления аргумента x решаемой функции, при котором решаемая функция равна нулю

сзаданной точностью eps.

6. Тип решаемой функции задается следующим описанием:

typedef double (*pef)(double);

7. Решаемая функция описывается в основном модуле следующим образом:

// Решаемая функция для метода деления отрезка пополам double f1(double x) {

/* код функции */

}

6

8. Функция метода вызывается в основной функции.

После вызова выводятся три строчки результата, например:

SUCCESS=9

EPSILON=0.001

RESULT1=1.254

Здесь:

SUCCESS — успешность выполнения алгоритма (значение success); EPSILON — заданная точность вычисления (значение EPS); RESULT1 — результат вычислений способом 1, вывод должен соот-

ветствовать заданной точности.

Порядок выполнения задания

1.Сначала выполните действия 1-11, описанные выше в разделе «Порядок выполнения первого задания».

2.Добавьте в решение новый модуль:

-выберите в меню Project Add New Item;

-в списке Categories выберите Code;

-в списке Templates выберите Header File (.h);

-в поле Name введите название модуля mhalfint;

-нажмите кнопку Add.

В проекте появится новый модуль.

Добавьте в новый модуль файловый комментарий согласно ТПМ, например, так:

/* Файл mhalfint.h

*/

/* ОТИ НИЯУ МИФИ

*/

/* 1ПО-XXД

*/

/* Пономарев Владимир Вадимович

*/

/* Вычислительная математика

*/

/* Программа VM1

*/

/*

Модуль метода деления отрезка пополам */

/*

20.02.2013

*/

3. Добавьте в модуль описание типа решаемой функции:

typedef double (*pef)(double);

4. Добавьте в модуль определение функции метода:

/* Метод деления отрезка пополам, способ 1 */

double halfint1(pef ef, double X1, double X2, double eps, int* success) {

}

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

7

5.Поскольку функция метода должна возвращать результат, впишите

внее следующий код для предварительной отладки:

double halfint1(pef ef, double X1, double X2, double eps, int* success) {

*success = 0; return ef(X1);

}

Здесь функция метода возвращает значение решаемой функции от X1.

6. Перейдите в основной модуль. В основной модуль включите библио-

теку математических функций math и модуль функции метода:

#include

"stdafx.h"

#include

<math.h>

/* Метод

деления отрезка пополам */

#include

"mhalfint.h"

7. Опишите константу, задающую заданную точность вычислений, например, так:

#include

"stdafx.h"

#include

<math.h>

/* Метод

деления отрезка пополам */

#include

"mhalfint.h"

/* Заданная точность вычислений */ #define EPS 0.001

8. Опишите решаемую функцию перед основной функцией, например:

/* Решаемая функция для метода деления отрезка пополам */ double f1(double x) {

return (x);

}

Название функции читается «эф один». На данном этапе разработки программы функция просто возвращает аргумент. Где-то далее по ходу выполнения работы вы замените код этой функции на нужный.

9. Перейдите в основную функцию (в основной модуль). Объявите в основной функции переменную для возвращаемого признака успешности алгоритма и переменную для возвращаемого результата, например, так:

/* Основная функция */ void _tmain() {

int success = 0; double result = 0.0;

}

10. Скомпилируйте проект, нажав, например, сочетание Ctrl+Shift+B. В случае возникновения ошибок устраните их.

8

11. Добавьте в основную функцию вызов функции метода для предварительной отладки, например, так:

void _tmain() {

int success = 0; double result = 0.0;

result = halfint1(f1, -1.0, 2.0, EPS, &success);

}

Заметим, что здесь "f1" — имя решаемой функции, "–1" — левая граница отрезка, "2" — правая граница отрезка, "EPS" — предполагаемая точность вычислений, "&success" — адрес переменной, указывающей на признак успешности выполнения алгоритма.

12. В основной функции добавьте код, который выводит результат вычислений, например, так:

void _tmain() {

int success = 0; double result = 0.0;

result = halfint1(f1, -1.0, 2.0, 0.001, &success); printf("SUCCESS=%d\n", success); printf("EPSILON=%0.3f\n", EPS); printf("RESULT1=%0.3f\n", result);

}

Заметим, что значения EPS и result следует выводить с необходимой точностью, поэтому при изменении точности EPS соответственно следует изменить также и спецификации вывода значений "%0.3f".

13.Скомпилируйте проект, нажав, например, сочетание Ctrl+Shift+B. В случае возникновения ошибок устраните их.

14.Запустите проект на выполнение, нажав сочетание клавиш Ctrl+F5. Убедитесь, что на консоль выводится:

ITERATION=0

EPSILON=0.001

RESULT1=-1.000

15.Основной модуль. Напишите код вычисления решаемой функции f1

всоответствии с заданием. Например, если решаемая функция задана следующим образом:

x + 1 = 0,

скорректируйте код решаемой функции так:

double f1(double x) { return (x + 1);

}

9

Определите границы начального отрезка и задайте их в вызове функции метода в основной функции. Например, если задана решаемая функция, приведенная в предыдущем пункте, то можно задать левую границу начального отрезка X1 = –2, правую границу X2 = 3 (решение равно –1):

result = halfint1(f1, -2.0, 3.0, EPS, &success);

Заметим, что желательно задать границы отрезка так, чтобы решение не лежало в центре начального отрезка, потому что в этом случае решение будет найдено в первой итерации, а это не интересно. В практических случаях, кстати, не всегда можно определить такие границы, чтобы решение находилось в центре. Дайте алгоритму возможность проявить себя! Пусть расстояние между границами и решением будет в соотношении, например, 1:4, 1:3, 1:2, 1:1.5. Кроме того, если функция не определена в некоторой точке x = a, то задайте отрезок, в который эта точка не входит.

16.Подготовительная работа завершена. Теперь ваша задача заключается в том, чтобы правильно организовать вычислительный процесс внут-

ри функций метода halfint1 и halfint2.

17.Организация вычислений, способ 1 (цикл завершается при обнаружении заданной точности).

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

Пусть точное решение находится между границами X1 и X2.

а) определим значение X, находящееся в середине отрезка [X1, X2]. б) вычислим значение решаемой функции g в точке X.

в) если значение g по абсолютной величине равно или не превышает заданную точность вычислений eps, то алгоритм достиг результата и завершается, при этом возвращается значение X.

г) вычислим значения решаемой функции g1 и g2 в точках X1 и X2. Заметим, что значения g1 и g2 должны иметь противоположные знаки.

Если это не так, отрезок [X1, X2] задан неверно, это ошибка.

д) Если произведение g×g1 меньше нуля (то есть значения g и g1 имеют разные знаки), то точное решение находится в отрезке [X1, X], и в этом случае границу X2 нужно заменить значением середины отрезка X (то есть присвоить границе X2 значение X). Если произведение g×g2 меньше нуля, то точное решение находится в отрезке [X, X2], и в этом случае границу X1 нужно заменить значением середины отрезка X.

В случае, если и g×g1 больше нуля, и g×g2 больше нуля, то алгоритм выполняется неверно, и его следует завершить с признаком ошибки.

е) перейти к следующей итерации, то есть к п.п. а).

Внутри функции, естественно, должны быть описаны локальные переменные X, g, g1, g2 типа double. Цикл реализуется оператором while (1).

10