Компания ALT Linux
Опубликован: 07.03.2015 | Доступ: свободный | Студентов: 2137 / 487 | Длительность: 24:14:00
Лекция 4:

Использование функций при программировании на C++

Задача 4.6. Задано число X в десятичной системе счисления. Выполнить перевод числа в системы счисления с основанием 2, 5 и 7.

Вообще, для того чтобы перевести целое число из десятичной системы счисления в другую, необходимо выполнить следующие действия:

  1. Разделить данное число на основание новой системы счисления: остаток от деления — младший разряд нового числа;
  2. Если частное от деления не равно нулю, продолжать деление, как указано в п.1.

На рис. 4.1 приведён пример "ручного" перевода числа 256, заданного в десятичной системе счисления, в восьмеричную. В результате получим 256_{(10)}=400_{(8)}

Пример перевода числа в новую систему счисления

Рис. 4.1. Пример перевода числа в новую систему счисления

Далее приведён текст программы, реализующей решение задачи 4.6.

#include <iostream>
using namespace std;
unsigned long long int NC( unsigned long long int N, unsigned int b )
{
	unsigned long long int S, P;
	for ( S=0,P=1;N!=0; S+=N%b *P, P*=10,N/=b );
	return S;
}
int main ( )
{
	unsigned long long int X;
	cout<<"X="; cin >>X; //Ввод числа X.
	//Перевод числа X в заданные системы счисления.
	cout<<X<<" (10) ="<<NC(X, 2 )<<" (2) "<<endl;
	cout<<X<<" (10) ="<<NC(X, 5 )<<" (5) "<<endl;
	cout<<X<<" (10) ="<<NC(X, 7 )<<" (7) "<<endl;
	return 0;
}
		

Задача 4.7. Найти корни уравнения x^2-\cos (5\cdot x)=0.

Для решения задачи использовать:

  • метод половинного деления,
  • метод хорд,
  • метод касательных (метод Ньютона),
  • метод простой итерации.

Оценить степень точности предложенных численных методов, определив, за сколько итераций был найден корень уравнения. Вычисления проводить с точностью \varepsilon=10^{-3}.

Вообще говоря, аналитическое решение уравнения

f(x) = 0 ( 4.1)
можно найти только для узкого класса функций. В большинстве случаев приходится решать уравнение (4.1) численными методами. Численное решение уравнения (4.1) проводят в два этапа: сначала необходимо отделить корни уравнения, т.е. найти достаточно тесные промежутки, в которых содержится только один корень, эти промежутки называют интервалами изоляции корня; на втором этапе проводят уточнение отделённых корней, т.е. находят корни с заданной точностью.

Интервал можно выделить, изобразив график функции, или каким-либо другим способом. Но все способы основаны на следующем свойстве непрерывной функции: если функция f (x) непрерывна на интервале [a, b] и на его концах имеет различные знаки, f (a) \cdot f (b) < 0, то между точками имеется хотя бы один корень. Будем считать интервал настолько малым, что в нём находится только один корень. Рассмотрим самый простой способ уточнения корней.

Графическое решение задачи 4.7 показано на рис. 4.2. Так как функция f(x)=x^2-\cos (5\cdot x) дважды пересекает ось абсцисс, можно сделать вывод о наличии в уравнении x^2-\cos (5\cdot x)=0 двух корней. Первый находится на интервале [-0.4; -0.2], второй принадлежит отрезку [0.2; 0.4] .

Геометрическое решение задачи 4.7

Рис. 4.2. Геометрическое решение задачи 4.7

Рассмотрим предложенные в задаче численные методы решения нелинейных уравнений.

Метод половинного деления (дихотомии). Пусть был выбран интервал изоляции [a, b] (рис. 4.3). Примем за первое приближение корня точку c, которая является серединой отрезка [a, b].Далее будем действовать по следующему алгоритму:

  1. Находим точку c=\frac{a+b}{2};
  2. Находим значение f (c);
  3. Если f(a)\cdot f(c)<0, то корень лежит на интервале [a, c], иначе корень лежит на интервале [c, b];
  4. Если величина интервала меньше либо равна \varepsilon, то найден корень с точностью \varepsilon, иначе возвращаемся к п.1.

Итак, для вычисления одного из корней уравнения  x^2-\cos (5\cdot x)=0 методом половинного деления достаточно знать интервал изоляции корня a=0.2;b=0.4 и точность вычисления \varepsilon=10^{-3}.

Блок-схема алгоритма решения уравнения методом дихотомии приведена на рис. 4.4. Понятно, что здесь c — корень заданного уравнения.

Однако, несмотря на простоту, такое последовательное сужение интервала проводится редко, так как требует слишком большого количества вычислений.

Графическая интерпретация метода половинного деления

Рис. 4.3. Графическая интерпретация метода половинного деления

Кроме того, этот способ не всегда позволяет найти решение с заданной точностью. Рассмотрим другие способы уточнения корня. При применении этих способов будем требовать, чтобы функция f (x) удовлетворяла следующим условиям на интервале [a, b] :

  1. функция f (x) непрерывна вместе со своими производными первого и второго порядка. Функция f (x) на концах интервала [a, b] имеет разные знаки f(a)\cdot f(b)<0;
  2. первая и вторая производные f'(x) и f''(x) сохраняют определённый знак на всём интервале [a, b] .

Метод хорд. Этот метод отличается от метода дихотомии тем, что очередное приближение берём не в середине отрезка, а в точке пересечения с осью X (рис. 4.5) прямой, соединяющей точки (a, f (a)) и (b, f (b)).

Запишем уравнение прямой, проходящей через точки с координатами (a, f (a)) и (b, f (b)) :

\frac{y-f(a)}{f(b)-f(a)}=\frac{x-a}{b-a},\ \ \  y=\frac{f(b)-f(a)}{b-a}\cdot (x-a)+f(a) ( 4.2)

Прямая, заданная уравнением (4.2), пересекает ось X при условии y = 0.

Найдём точку пересечения хорды с осью X: y=\frac{f(b)-f(a)}{b-a}\cdot (x-a)+f(a),\ \  x=a-\frac{f(a)\cdot (b-a)}{f(b)-f(a)}. итак, c=a-\frac{f(a)}{f(b)-f(a)}(b-a).

Далее необходимо вычислить значение функции в точке c. Это и будет приближённое значение корня уравнения.

Алгоритм решения уравнения методом дихотомии

Рис. 4.4. Алгоритм решения уравнения методом дихотомии

Для вычисления одного из корней уравнения x^2-\cos (5\cdot x)=0 методом хорд достаточно знать интервал изоляции корня, например, a = 0.2; b = 0.4, и точность вычисления \varepsilon=10^{-3}. Блок-схема метода представлена на рис. 4.6.

Метод касательных (метод Ньютона). В одной из точек интервала [a; b], пусть это будет точка a, проведём касательную (рис. 4.7). Запишем уравнение этой прямой:

y=k\cdot x+m ( 4.3)

Так как эта прямая является касательной, и она проходит через точку (c,f(c)), то k=f'(c).

Следовательно, y=f'(x)\cdot x+m,f(c)=f'(c)\cdot c+m,m=f(c)-c\cdot f'(c),\\y=f'(c)\cdot x+f(c)-c\cdot f'(c),y=f'(c)\cdot (x-c)+f(c).

Найдём точку пересечения касательной с осью X: f'(c)\cdot (x-c)+f(c)=0,\ \ x=c-\frac{f(c)}{f'(c)}

Графическая интерпретация метода хорд

Рис. 4.5. Графическая интерпретация метода хорд

Если |f(x)|<\varepsilon, то точность достигнута, и точка x — решение; иначе необходимо переменной c присвоить значение x и провести касательную через новую точку c; так продолжать до тех пор, пока |f (x)| не станет меньше \varepsilon. Осталось решить вопрос, что выбрать в качестве точки начального приближения c.

В этой точке должны совпадать знаки функции и её второй производной. А так как нами было сделано допущение, что вторая и первая производные не меняют знак, то можно проверить условие f(x)\cdot f''(x)>0 на обоих концах интервала, и в качестве начального приближения взять ту точку, где это условие выполняется.

Здесь, как и в предыдущих методах, для вычисления одного из корней уравнения x^2-\cos (5\cdot x)=0 достаточно знать интервал изоляции корня, например, a = 0.2; b = 0.4, и точность вычисления \varepsilon=10^{-3}. Блок-схема метода Ньютона представлена на рис. 4.8. Понятно, что для реализации этого алгоритма нужно найти первую и вторую производные функции f(x)=x^2-\cos (5\cdot x):  f'(x)=2\cdot x+5\cdot \sin (5\cdot x), 	f(x) =2 +25 \cdot cos(5 \cdot x).

Метод простой итерации. Для решения уравнения этим методом необходимо записать уравнение (4.1) в виде x=\phi(x), задать начальное приближение x_0\in [a;b] и организовать следующий итерационный вычислительный процесс: x_{k+1}=\phi(x_k),k=0,1,2,...

Вычисление прекратить, если |x_{k+1}-x_k|<\varepsilon (\varepsilon — точность).

Если неравенство |\phi'(x)|<1 выполняется на всём интервале [a; b], то последовательность x_0, x_1, x_2,...,x_n,... 	, ... сходится к решению x^* (т.е. l\lim\limits_{k\rightarrow \infty}x_k=x^*).

Значение функции \phi(x) должно удовлетворять условию |\phi'(x)|<1 для того, чтобы можно было применить метод простых итераций. Условие |\phi'(x)|<1 является достаточным условием сходимости метода простой итерации.

Алгоритм метода хорд

Рис. 4.6. Алгоритм метода хорд

Уравнение (4.1) можно привести к виду x=\phi(x) следующим образом. Умножить обе части уравнения f (x) = 0 на число \lambda. К обеим частям уравнения \lambda\cdot f(x)=0 добавить число x. Получим x=x+\lambda\cdot f(x). Это и есть уравнение вида x=\phi(x), где

\phi(x)=x+\lambda\cdot f(x) ( 4.4)

Необходимо чтобы неравенство |\phi"(x)|<1 выполнялось на интервале [a; b], следовательно, |\phi"(x)|=|1+\lambda\cdot f'(x)| и |1+\lambda\cdot f'(x)|<1  (|1+\lambda\cdot f'(a)|<1,  |1+\lambda\cdotf'(b)|<1), а значит, с помощью подбора параметра \lambda можно добиться выполнения условия сходимости.

Для вычисления корней уравнения x^2-\cos (5\cdot x)=0 воспользуемся графическим решением (рис. 4.2) и определим интервал изоляции одного из корней, например, a = 0.2; b = 0.4. Подберём значение \lambda, решив неравенство |1+\lambda\cdot f'(x)|<1:|1+\lambda\cdot f'(a)|<1 и |1+\lambda\cdot f'(b)|<1,\\f(x)=x^{2}-\cos (5\cdot x),f'(x)=2\cdot x+5\cdot \sin (5\cdot x),\\f'(a)=2\cdot 0.2+5\cdot \sin (5\cdot 0.2)\approx 4.6,  f'(b)=2\cdot 0.4+5\cdot \sin (5\cdot 0.4)\approx 5.35,\\|1+\lambda\cdot 4.6|<1 и |1+\lambda\cdot 5.35|<1. \left\{\begin{array}{l}
					\left\{\begin{array}{l}
					1+4.6\cdot \lambda<1 \cr
					1+4.6\cdot \lambda>-1
					\end{array}\right.\cr
					\left\{\begin{array}{l}
					\lambda<0 \cr
					\lambda>-0.37
					\end{array}\right.
					\end{array}\right.
					\Rightarrow
					\left\{\begin{array}{l}
					\left\{\begin{array}{l}
					\lambda<0 \cr
					\lambda>-0.4
					\end{array}\right.\cr
					\left\{\begin{array}{l}
					\lambda<0 \cr
					\lambda>-0.37
					\end{array}\right.
					\end{array}\right.
					\Rightarrow
					\left\{\begin{array}{l}
					\lambda\in (-0.4;0) \cr
					\lambda\in (-0.37;0)
				\end{array}\right.

и, следовательно, \lambda\in (-0.37;0).

Графическая интерпретация метода касательных

Рис. 4.7. Графическая интерпретация метода касательных

Таким образом, исходными данными для программы будут начальное значение корня уравнения x_0=0.2, значение параметра \lambda (пусть \lambda= -0.2), и точность вычислений \varepsilon=0.001.

Для вычисления второго корня заданного уравнения параметр \lambda подбирают аналогично.

Блок-схема метода простой итерации приведена на рис. 4.9.

Далее представлен текст программы, реализующий решение задачи 4.7.

#include <iostream>
#include <math.h>
using namespace std;
//Функция, определяющая левую часть уравнения f (x) = 0.
double f ( double x )
{
	return ( x *x-cos (5 * x ) );
}
//Функция, реализующая метод половинного деления.
int Dichotomy ( double a, double b, double * c, double eps )
{ int k=0;
	do
	{
		* c=(a+b ) / 2;
		if ( f ( * c ) * f ( a ) <0) b=*c;
		else a=*c;
		k++;
	}
	while ( fabs ( a-b )>=eps );
	return k;
}
//Функция, реализующая метод хорд.
int Chord ( double a, double b, double * c, double eps )
{ int k=0;
	do
	{
		* c=a-f ( a ) /( f ( b )-f ( a ) ) * ( b -a );
		if ( f ( * c ) * f ( a ) >0) a=*c;
		else b=*c;
		k++;
	}
	while ( fabs ( f ( * c ) )>=eps );
	return k;
}
double f1 ( double x ) //Первая производная функции f (x).
{
	return (2 * x+5* sin (5 * x ) );
}
double f2 ( double x ) //Вторая производная функции f (x).
{
	return (2+25* cos (5 * x ) );
}
//Функция, реализующая метод касательных.
int Tangent ( double a, double b, double * c, double eps )
{ int k=0;
	if ( f ( a ) * f2 ( a ) >0) * c=a;
	else * c=b;
	do
	{
		* c=*c-f (* c ) / f1 ( * c );
		k++;
	}
	while ( fabs ( f ( * c ) )>=eps );
	return k;
}
double fi ( double x, double L) //Функция, заданная выражением 4.4 .
{
	return ( x+L* f ( x ) );
}
//Функция, реализующая метод простой итерации.
int Iteration ( double *x, double L, double eps )
{ int k=0; double x0;
	do
	{
		x0=*x;
		*x= fi(x0, L);
		k++;
	}
	while ( fabs ( x0-*x )>=eps );
	return k;
}
int main ( )
{
	double A, B, X, P;
	double ep =0.001; //Точность вычислений.
	int K;
	cout<<"a="; cin >>A; //Интервал изоляции корня.
	cout<<"b="; cin >>B;
	cout<<"Решение уравнения x^2 - cos (5* x) =0. "<<endl;
	cout<<"Метод дихотомии:"<<endl;
	K=Dichotomy (A, B,&X, ep );
	cout<<"Найденное решение x="<<X;
	cout<<", количество итераций k="<<K<<endl;
	cout<<"Метод хорд:"<<endl;
	K=Chord (A, B,&X, ep );
	cout<<" Найденное решение x="<<X;
	cout<<", количество итераций k="<<K<<endl;
	cout<<"Метод касательных:"<<endl;
	K=Tangent (A, B,&X, ep );
	cout<<" Найденное решение x="<<X;
	cout<<", количество итераций k="<<K<<endl;
	cout<<"Метод простой итерации:"<<endl;
	X=A;
	cout<<"L="; cin >>P;
	K=Iteration (&X, P, ep );
	cout<<" Найденное решение x="<<X;
	cout<<", количество итераций k="<<K<<endl;
	return 0;
}
				
Алгоритм метода Ньютона

Рис. 4.8. Алгоритм метода Ньютона
Алгоритм метода простой итерации

Рис. 4.9. Алгоритм метода простой итерации

Результаты работы программы:

a=0.2
b=0.4
Решение уравнения x^2-cos(5*x)=0.
Метод дихотомии:
Найденное решение x=0.296094, количество итераций k=8
Метод хорд:
Найденное решение x=0.296546, количество итераций k=2
Метод касательных:
Найденное решение x=0.296556, количество итераций k=2
Метод простой итерации:
L=-0.2
Найденное решение x=0.296595, количество итераций k=3
				
Сергей Радыгин
Сергей Радыгин

Символы кириллицы выводит некорректно. Как сделать чтобы выводился читабельный текст на русском языке?

Тип приложения - не Qt,

Qt Creator 4.5.0 основан на Qt 5.10.0. Win7.

 

Юрий Герко
Юрий Герко

Кому удалось собрать пример из раздела 13.2 Компоновка (Layouts)? Если создавать проект по изложенному алгоритму, автоматически не создается  файл mainwindow.cpp. Если создавать этот файл вручную и добавлять в проект, сборка не получается - компилятор сообщает об отсутствии класса MainWindow. Как правильно выполнить пример?