Из предыдущих глав известно, что массив это переменная для хранения множества данных одного типа. Если возникает необходимость обрабатывать разнородную информацию как единое целое, то применяют тип данных структуры. Он позволяет сгруппировать объекты различных типов данных под одним именем.
Для того, чтобы объявить переменные структурного типа, вначале нужно задать новый тип данных, указав имя структуры и её элементы. Элементы структуры называются полями, и могут иметь любой тип данных кроме типа этой же структуры. Далее приведён пример создания структурного типа student, полями которого являются фамилия студента, шифр группы, год начала обучения и оценки по четырём предметам:
struct student
{
//Поля структуры:
char fio [ 30 ];
char group [ 8 ];
int year;
int informatika, math, fizika, history;
}
На основании созданного структурного типа данных можно описать переменные типа student:
student Vasya; //Переменная Vasya типа student. student ES [ 50 ]; //Массив, элементы которого имеют тип student. student *x; //Указатель на тип данных student
Обращаются к полям переменной структурного типа так:
имя_структуры.поле
Например,
Vasya.year; //Обращение к полю year переменной Vasya. ES[4].math; //Обращение к полю math элемента ES[4].
Задача 9.1. Задано $$n$$ комплексных чисел, которые хранятся в двоичном файле. Найти значение наибольшего модуля среди заданных чисел.
Напомним, что комплексные числа это числа вида $$z=a+b\cdot i$$, где $$a$$ и $$b$$ — действительные числа, а $$i$$ — мнимая единица, $$i^2=-1$$. Комплексное число расширяет понятие действительного числа. Если действительное число — это любая точка на числовой прямой, то под комплексным числом понимают точку на плоскости (рис. 9.1). Модуль комплексного числа $$z$$ вычисляют по формуле $$|z|=\sqrt{a^2+b^2}$$.
Для решения задачи 9.1 разработаны две программы. Первая создаёт файл исходных данных, вторая получает из него информацию и обрабатывает её в соответствии с поставленной задачей.
Далее приведён текст программы создания двоичного файла с $$n$$ комплексными числами. В файл complex.dat будет записано число n, а затем последовательно комплексные числа.
#include <iostream>
#include <fstream>
using namespace std;
int main ( )
{
//Структура Комплексное число.
struct complex
{
//Поля структуры:
double Re; //Действительная часть.
double Im; //Мнимая часть.
};
complex p; //Переменная для хранения комплексного чисела.
int i, n;
FILE *f;
cout<<" n = "; cin>>n;
f=fopen ( " complex.dat ", " wb " );
fwrite (n, sizeof ( int ), 1, f );
for ( i =0; i<n; i++)
{
cout<<"Введите комплексное число\n ";
//Ввод комплексного числа:
cin>>p.Re; //действительная часть,
cin>>p.Im; //мнимая часть.
//Вывод комплексного числа.
cout<<p.Re<<" + "<<p.Im<<" i "<<endl;
//Запись комплексного числа в двоичный файл.
fwrite (p, sizeof ( complex ), 1, f );
}
fclose ( f );
return 0;
}
(рис 9.1) Геометрическая модель комплексного числа a + b · i
(рис 9.2) Геометрическая интерпретация комплексно-сопряжённого числа
Следующая программа считывает информацию из файла complex.dat — количество комплексных чисел в переменную n, а сами комплексные числа в массив p. Затем происходит поиск комплексного числа с максимальным модулем в массиве p.
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{
struct complex
{
double Re;
double Im;
};
complex *p;
int i, n, nmax;
double max;
FILE *f;
f=fopen ( " complex.dat ", " rb " );
fread (n, sizeof ( int ), 1, f );
p=new complex [ n ];
fread ( p, sizeof ( complex ), n, f );
//Поиск комплексного числа с максимальным модулем
max=sqrt ( p[0].Re*p[0].Re+p[0].Im*p[0].Im );
for ( i =1,nmax=0; i<n; i++)
if ( sqrt ( p[i].Re*p[i].Re+p[i].Im*p[i].Im )>max)
{
max=sqrt ( p[i].Re*p[i].Re+p [i].Im*p[i].Im );
nmax= i;
}
cout<<" max = "<<max<<" \t nmax = "<<nmax<<endl;
fclose ( f );
return 0;
}
Задача 9.2. Даны два комплексных числа $$z_1$$ и $$z_2$$. Выполнить над ними основные операции:
Суммой двух комплексных чисел $$z_1=a+i\cdot b$$ и $$z_2=c+i\cdot d$$ называется комплексное число $$z=z_1+z_2=(a+c)+i\cdot (b+d)$$.
Разностью двух комплексных чисел $$z_1=a+i\cdot b$$ и $$z_2=c+i\cdot d$$ называется комплексное число $$z=z_1-z_2=(a-c)+i\cdot (b-d)$$.
Произведением двух комплексных чисел $$z_1=a+i\cdot b$$ и $$z_2=c+i\cdot d$$ называется комплексное число $$z=z_1\cdot {z_2}=(a\cdot c-b\cdot d)+i\cdot (b\cdot c+a\cdot d)$$.
Частным двух комплексных чисел $$z_1=a+i\cdot b$$ и $$z_2=c+i\cdot d$$ называется комплексное число $$z=\frac{z_1}{z_2}=\frac{ac+bd}{c^2+d^2}+i\cdot {\frac{bc-ad}{c^2+d^2}}$$ Числом, сопряжённым комплексному числу $$z=x+i\cdot y$$, называется число $$\bar{z}=x-i\cdot y$$ (рис. 9.2).
Всякое комплексное число, записанное в алгебраической форме $$z=x+i\cdot y$$, можно записать в тригонометрической $$z=r(\cos \phi+i\cdot \sin \phi)$$ или в показательной форме $$z=r\cdot e^{i\cdot \phi}$$, где $$r=\sqrt{x^2+y^2}$$ — модуль комплексного числа $$z,\ \phi=\arctan \frac{y}{x}$$— его аргумент (рис. 9.2).
Для возведения в степень комплексного числа, записанного в тригонометрической форме $$z=r(\cos\phi+i\cdot \sin \phi$$), можно воспользоваться формулой Муавра $$z^n=r^n\cdot (\cos (n\cdot \phi)+i\cdot \sin (n\cdot \phi)).$$ Формула для извлечения корня $$n$$-й степени из комплексного числа $$z=r\cdot (\cos \phi+i\cdot \sin \phi)$$ имеет вид $$\sqrt[n]z=\sqrt[n]z(\cos \frac{\phi+2\cdot \pi \cdot k}{n}+i\cdot \sin \frac{\phi+2\cdot \pi \cdot k}{n}),$$ где $$n>1,k=0,1,\dots,n-1$$.
Далее приведён текст программы, реализующий алгоритм решения задачи 9.2. В программе описаны две структуры для работы с комплексными числами: структура complex1 для представления комплексных чисел в алгебраической форме (Re — действительная часть комплексного числа, Im — его мнимая часть) и структура complex2 для представления комплексных чисел в показательной или тригонометрической форме (Modul — модуль комплексного числа, Argum — его аргумент). Кроме того в программе созданы функции, реализующие основные действия над комплексными числами, переход между различными формами представления комплексных чисел, а также ввод-вывод комплексных чисел.
#include <iostream>
#include <math.h>
using namespace std;
struct complex1
{
float Re;
float Im;
};
struct complex2
{
float Modul;
float Argum;
};
//Ввод числа в алгебраической форме
complex1 vvod1 ( )
{
complex1 temp;
cout<<"Введите действительную часть числа\n ";
cin>>temp.Re;
cout<<"Введите мнимую часть комплексного числа\n ";
cin>>temp.Im;
return temp;
}
//Ввод числа в тригонометрической или показательной форме
complex2 vvod2 ( )
{
complex2 temp;
cout<<"Введите модуль комплексного числа\n ";
cin>>temp.Modul;
cout<<"Введите аргумент комплексного числа\n ";
cin>>temp.Argum;
return temp;
}
//Вывод числа в алгебраической форме
void vivod ( complex1 chislo )
{
cout<<chislo.Re;
if ( chislo.Im>=0)
cout<<" + "<< chislo.Im<<" i "<<endl;
else
cout<<" "<< chislo.Im<<" i "<<endl;
}
//Вывод числа в тригонометрической форме
void vivod ( complex2 chislo )
{
cout<<chislo.Modul<<" ( cos ( "<< chislo.Argum<<" ) + i sin ( "<< chislo.Argum<<
" ) ) "<<endl;
}
//Перевод числа из тригонометрической формы в алгебраическую,
//pr определяет, выводить или нет полученное число на экран.
complex1 perevod ( complex2 chislo, bool pr=false )
{
complex1 temp;
temp.Re=chislo.Modul*cos ( chislo.Argum );
temp.Im=chislo.Modul*sin ( chislo.Argum );
if ( pr ) vivod ( temp );
return temp;
}
//Перевод числа из алгебраической формы в тригонометрическую,
//pr определяет, выводить или нет полученное число на экран.
complex2 perevod ( complex1 chislo, bool pr=false )
{
complex2 temp;
temp.Modul=sqrt ( chislo.Re* chislo.Re+
chislo.Im*chislo.Im );
temp.Argum=atan ( chislo.Im/ chislo.Re );
if ( pr ) vivod ( temp );
return temp;
}
//Функция сложения двух чисел в алгебраической форме,
//pr определяет, выводить или нет число на экран.
complex1 plus1 ( complex1 chislo1, complex1 chislo2, bool pr=true )
{
complex1 temp;
temp.Re=chislo1.Re+chislo2.Re;
temp.Im=chislo1.Im+chislo2.Im;
if ( pr ) vivod ( temp );
return temp;
}
//Функция вычитания двух чисел в алгебраической форме,
//pr определяет, выводить или нет число на экран.
complex1 minus1 ( complex1 chislo1, complex1 chislo2, bool pr=true )
{
complex1 temp;
temp.Re=chislo1.Re-chislo2.Re;
temp.Im=chislo1.Im-chislo2.Im;
if ( pr ) vivod ( temp );
return temp;
}
//Функция умножения двух чисел в алгебраической форме,
//pr определяет, выводить или нет число на экран.
complex1 mult1 ( complex1 chislo1, complex1 chislo2, bool pr=true )
{
complex1 temp;
temp.Re=chislo1.Re* chislo2.Re-chislo1.Im* chislo2.Im;
temp.Im=chislo1.Im* chislo2.Re+chislo1.Re* chislo2.Im;
if ( pr ) vivod ( temp );
return temp;
}
//Функция деления двух чисел в алгебраической форме,
//pr определяет, выводить или нет число на экран.
complex1 divide1 ( complex1 chislo1, complex1 chislo2, bool pr=true )
{
complex1 temp;
temp.Re=( chislo1.Re* chislo2.Re+chislo1.Im* chislo2.Im ) / ( chislo2.Re* chislo2 .
Re+chislo2.Im* chislo2.Im );
temp.Im=( chislo1.Im* chislo2.Re-chislo1.Re* chislo2.Im ) / ( chislo2.Re* chislo2 .
Re+chislo2.Im* chislo2.Im );
if ( pr ) vivod ( temp );
return temp;
}
//Функция возведения комплексного числа в алгебраической форме
//в целую степень n, pr определяет, выводить или нет полученное число на экран.
complex1 pow1 ( complex1 chislo1, int n, bool pr=true )
{
complex1 temp;
complex2 temp2;
float p=1;
int i =1;
temp2=perevod ( chislo1, true ); //Перевод числа в тригонометрическую форму.
for (; i<=n; p*=temp2.Modul, i++);
temp.Re=p*cos ( n*temp2.Argum );
temp.Im=p*sin ( n*temp2.Argum );
if ( pr ) vivod ( temp );
return temp;
}
//Функция извлечения корня степени n из комплексного числа
//в алгебраической форме, pr определяет, выводить или нет
//полученные значения на экран. Функция возвращает ro и fi.
void sqrt n 1 ( complex1 chislo1, int n, float _ ro, float _ f i, bool pr=true )
{
complex1 temp;
complex2 temp2;
int i =0;
temp2=perevod ( chislo1, true ); //Перевод числа в тригонометрическую форму.
* r o=pow ( temp2.Modul, ( float ) 1/n );
* f i=temp2.Argum;
if ( pr )
{
for ( i =0; i<n; i++)
{
cout<<i<<"-е значение корня\n ";
temp.Re=*ro* cos ( ( * fi +2*M_PI* i ) /n );
temp.Im=*ro* sin ( ( * fi +2*M_PI* i ) /n );
vivod ( temp );
}
}
}
int main ( )
{
complex1 chislo1, chislo2; //Описание комплексных
complex1 chislo5; //чисел в алгебраической форме.
complex2 chislo3, chislo4; //Описание комплексных чисел в тригонометрической форме.
float ro1, fi1;
chislo1=vvod1 ( ); //Ввод исходных данных
chislo2=vvod1 ( ); //в алгебраической форме.
vivod ( chislo1 ); //Вывод исходных данных
vivod ( chislo2 ); //в алгебраической форме.
chislo 3=perevod ( chislo1, true ); //Перевод чисел
chislo 4=perevod ( chislo2, true ); //в тригонометрическую форму и вывод их на экран.
cout<<"Сумма чисел ";
chislo5=plus1 ( chislo1, chislo2, true );
cout<<"Разность чисел ";
chislo5=minus1 ( chislo1, chislo2, true );
cout<<"Произведение чисел ";
chislo5=mult1 ( chislo1, chislo2, true );
cout<<"Частное чисел ";
chislo5=divide1 ( chislo1, chislo2, true );
chislo5=pow1 ( chislo1, 5, true ); //Возведение числа в пятую степень.
sqrtn1 ( chislo1, 5, Ro1, fi1, true ); //Извлечение корня пятой степени.
return 0;
}
Результаты работы программы к задаче 9.2.
Введите действительную часть числа 5 Введите мнимую часть комплексного числа -7 Введите действительную часть числа 11 Введите мнимую часть комплексного числа 1.85 5 -7 i 11 +1.85 i 8.60233 ( cos (-0.950547) + i sin (-0.950547)) 11.1545 ( cos (0.166623) + i sin (0.166623)) Сумма чисел 16 -5.15 i Разность чисел -6 -8.85 i Произведение чисел 67.95 -67.75 i Частное чисел 0.337961 -0.693203 i 8.60233 ( cos (-0.950547) + i sin (-0.950547)) 1900 +47068 i 8.60233 ( cos (-0.950547) + i sin (-0.950547)) 0-е значение корня 1.51018 -0.290608 i 1-е значение корня 0.743054 +1.34646 i 2-е значение корня -1.05094 +1.12277 i 3-е значение корня -1.39257 -0.652552 i 4-е значение корня 0.190285 -1.52606 i
Работа с комплексными числами в C++ реализована с помощью библиотеки complex. Подключение этой библиотеки даёт возможность применять операции +, _, *, / для работы не только с вещественными, но и с комплексными числами.
Перед подключением библиотеки complex обязательно необходимо подключить библиотеку math.h.
Для определения переменной типа комплексное число используется оператор.
complex <тип_переменной> имя_переменной;
Здесь тип_переменной — это любой допустимый в C++ числовой тип данных (int, long int, double, float и т. д.), описывающий действительную и мнимую части комплексного числа. Например,
complex <float > x, y, z [ 5 ], * r; complex <double> a; complex <int> a, b, c;
Для организации ввода-вывода комплексных чисел можно использовать библиотеку iostream и стандартные конструкции cin, cout. Например,
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
int main ( int arg c, char ** argv )
{
complex <double> b, c; //Описание комплексных чисел.
cout<<" b = "; cin>>b; //Ввод комплексного числа b.
cout<<" c = "; cin>>c; //Ввод комплексного числа c.
cout<<" b / c = "<<b/ c; //Вывод частного комплексных чисел
return 0;
}
В результате получим:
b=(1.24,-6.12) c=(9.01,-11.22) b/c=(0.385567,-0.199105)
Обратите внимание, что при вводе комплексных чисел с клавиатуры действительная и мнимая части вводятся в скобках через запятую:
(действительная_часть, мнимая_часть)
Далее приведён пример присваивания комплексным переменным реальных значений при их описании:
complex <double> z ( 4.0, 1.0 ); complex <int> r ( 4, -7);
Следующий пример демонстрирует, как из двух числовых значений можно составить комплексное число:
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
int main ( int arg c, char ** argv )
{
double x1, y1;
x1=-2.3;
y1 = 8.1;
complex <double> b ( x1, y1 ); //Формирование комплексного числа b
//с действительной частью x1 и мнимой y1.
cout<<" b ^ 2 = "<<b*b; //Вывод квадрата комплексного числа.
return 0;
}
В табл. 9.1 представлены основные математические функции для работы с комплексными числами.
| Прототип функции | Описание функции |
|---|---|
double abs(complex z) |
Возвращает модуль комплексного числа $$z$$. |
double arg(complex z) |
Возвращает значение аргумента комплексного числа $$z$$ |
complex conj(complex z) |
Возвращает число комплексно сопряжённое числу $$z$$ |
complex cos(complex z) |
Возвращает косинус комплексного числа $$z$$ |
complex cosh(complex z) |
Возвращает гиперболический косинус комплексного числа $$z$$. |
complex exp(complex z) |
Возвращает экспоненту комплексного числа $$z$$. |
double imag(complex z) |
Возвращает мнимую часть комплексного числа $$z$$. |
complex log(complex z) |
Возвращает натуральный логарифм комплексного числа $$z$$ |
complex log10(complex z) |
Возвращает десятичный логарифм комплексного числа $$z$$. |
double norm(complex z) |
Возвращает квадрат модуля комплексного числа $$z$$. |
complex pow(complex x, complex y) |
Возвращает степень комплексного числа $$z$$. |
complex polar(double mag, double angle) |
Формирует комплексное число с модулем $$mag$$ и аргументом $$angle.$$ |
double real(complex z) |
Возвращает действительную часть комплексного числа $$z$$ |
complex sin(complex z) |
Возвращает синус комплексного числа $$z$$ |
complex sinh(complex z) |
Возвращает гиперболический синус комплексного числа $$z$$. |
complex sqrt(complex z) |
Возвращает квадратный корень комплексного числа $$z$$ |
complex tan(complex z) |
Возвращает тангенс комплексного числа $$z$$ |
complex tanh(complex z) |
Возвращает гиперболический тангенс комплексного числа $$z$$. |
Далее приведён текст программы, демонстрирующий работу с некоторыми функциями из табл. 9.1.
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
int main ( )
{
complex <double> x ( 4, -6);
complex <double> y (-7, 2 );
cout<<" x * y = "<<x*y<<endl;
cout<<" sin ( x ) * cos ( y ) = "<<sin ( x ) * cos ( y )<<endl;
cout<<" conj ( x ) * ln ( y ) = "<<conj ( x ) * log ( y )<<endl;
cout<<" sh ( y ) = "<<sinh ( y )<<endl;
return 0;
}
Результаты работы программы с некоторыми функциями комплексного аргумента:
x*y=(-16,50) sin(x)*cos(y)=(-747.159,10.2102) conj(x)*ln(y)=(-9.23917,23.364) sh(y)=(228.18,498.583)
Задача 9.3. Вычислить $$y={(\sqrt{3}-i)}^{20},\ z=\left(\frac{1+i\cdot \sqrt{3}}{1-i}\right)^{40}$$.
Если провести аналитические преобразования, то получим следующее:
$$y=2^{19}\cdot (-1+i\cdot \sqrt{3}),\ z=-2^{19}\cdot (1+i\cdot \sqrt{3}).$$Проверим эти вычисления с помощью программы на C++. Результаты работы программы подтверждают аналитические вычисления.
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
int main ( )
{
complex <double> b ( sqrt ( 3 ),-1), y;
y=pow ( b, 20 );
cout<<" y = "<<y<<endl;
cout<<real ( y ) /pow ( 2, 1 9 )<<" \t ";
cout<<imag ( y ) /pow ( 2, 1 9 )<<" \n ";
complex <double> a ( 1, sqrt ( 3 ) ), c (1, -1), z;
z=pow ( a / c, 40 );
cout<<" z = "<<z<<endl;
cout<<real ( z ) /pow ( 2, 19 )<<" \t ";
cout<<imag ( z ) /pow ( 2, 19 )<<" \n ";
return 0;
}
Результаты работы программы к задаче 9.3:
b=(1.73205,-1)y=(-524288,908093) -1 1.73205 z=(-524288,-908093) -1 -1.73205
Операции с массивами, элементами которых являются комплексные числа, осуществляются так же, как и с обычными переменными. В качестве примера рассмотрим следующие задачи.
Задача 9.4. Написать программу умножения матриц комплексных чисел. Матрицы $$A$$ и $$B$$ имеют вид:
$$A=\left(\begin{array}{rrrr}1+2\cdot i2+3\cdot i3+1.54\cdot i4-7.2\cdot i\\2+5\cdot i3+7\cdot i4+10\cdot i5+14\cdot i\\1.5+3.25\cdot i1.7-3.94\cdot i6.23+11.17\cdot i-4.12+3.62\cdot i\end{array}\right), \noindent B=\left(\begin{array}{rrrrr}6.23-1.97\cdot i0.19+0.22\cdot i0.16+0.28\cdot i3.4+1.95\cdot i2.20-0.18\cdot i\\0.22+0.29\cdot i11+12\cdot i6.72-1.13\cdot i16+18\cdot i34+66\cdot i\\5+1\cdot i1.4-1.76\cdot i4.5+2.3\cdot i296+700\cdot i4.2+1.03\cdot i\\-3.4-2.61\cdot i1+11\cdot i2+23\cdot i3-35\cdot i4+47\cdot i\end{array}\right).$$Пусть исходные данные хранятся в файле abc.txt. Данные к задаче 9.4, содержимое файла abc.txt:
3 4 5 (1,2) (2,3) (3,1.54) (4,-7.2) (2,5) (3,7) (4,10) (5,14) (1.5,3.25) (1.7,-3.94) (6.23,11.17) (-4.12,3.62) (6.23,-1.97) (0.19,0.22) (0.16,0.28) (3.4,1.95) (2.20,-0.18) (0.22,0.29) (11,12) (6.72,-1.13) (16,18) (34,66) (5,1) (1.4,-1.76) (4.5,2.3) (296,700) (4.2,1.03) (-3.14,-2.61) (1,11) (2,23) (3,-35) (4,47)
Далее приведён текст программы, реализующий алгоритм решения задачи 9.4.
#include <iostream>
#include <fstream>
#include <math.h>
#include <complex>
using namespace std;
int main ( )
{
int i, j, p,N,M,K;
complex <float > **A, **B, **C;
ifstream f;
ofstream g;
f.open ( " abc.txt " );
f>>N>>M>>K;
cout<<" N = "<<N<<" \tM = "<<M<<" \tK = "<<K<<endl;
A=new complex <float > * [N ];
for ( i =0; i<N;A [ i ]=new complex <float > [M], i++);
B=new complex <float > * [M];
for ( i =0; i<M;B [ i ]=new complex <float > [K ], i++);
C=new complex <float > * [N ];
for ( i =0; i<N;C [ i ]=new complex <float > [K ], i++);
for ( i =0; i<N; i++)
for ( j =0; j<M; f>>A [ i ] [ j ], j++);
cout<<"Матрица A\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<M; cout<<A [ i ] [ j ]<<" \t ", j++);
for ( i =0; i<M; i++)
for ( j =0; j<K; f>>B [ i ] [ j ], j++);
cout<<"Матрица B\n ";
for ( i =0; i<M; cout<<endl, i++)
for ( j =0; j<K; cout<<B [ i ] [ j ]<<" \t ", j++);
for ( i =0; i<N; i++)
for ( j =0; j<K; j++)
for (C [ i ] [ j ]=p=0;p<M; p++)
C [ i ] [ j ]+=A [ i ] [ p ] *B [ p ] [ j ];
f.close ( );
cout<<"Матрица C\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<K; cout<<C [ i ] [ j ]<<" \t ", j++);
g.open ( " result.t x t " );
g<<"Матрица C=A*B\n ";
for ( i =0; i<N; g<<endl, i++)
for ( j =0; j<K; g<<C [ i ] [ j ]<<" \t ", j++);
g.close ( );
return 0;
}
Результат умножения матриц из задачи 9.4 (файл result.txt):
Матрица C=A*B (-8.152,34.598) (75.8604,91.276) (199.988,109.93) (-452.5,2486.99) (237.974,406.978) (51.78,26.61) (-177.52,190.35) (-290.01,242.21) (-5391.95,5813.9) (-986.2,783.76) (59.6291,78.3851) (49.9912,-59.0193) (-82.8542,-50.3838) (-5763.7,7803.92) (149.766,-140.709)
Задача 9.5. Заданы матрицы $$A$$ и $$B$$. Необходимо вычислить матрицу $$A^{-1}$$, обратную к матрице $$A$$, найти определитель $$|A|$$ матрицы $$A$$ и решить матричное уравнение $$A\cdot X=B$$, где $$X=A^{-1}\cdot B$$. Матрицы $$A$$ и $$B$$ имеют вид:
$$A=\left(\begin{array}{rrr}1+2\cdot i2+3\cdot i3+1.54\cdot i\\2+5\cdot i3+7\cdot i4+10\cdot i\\1.5+3.25\cdot i1.7-3.94\cdot i6.23+11.17\cdot i\end{array}\right), B=\left(\begin{array}{rrr}1.5+3.25\cdot i1.7-9.34\cdot i6.23+11.17\cdot i\\0.11+8.22\cdot i0.34-18.21\cdot i1-7\cdot i\\1+5\cdot i7-13\cdot i12+89\cdot i\end{array}\right).$$Для хранения исходных данных создадим текстовый файл abc2.txt следующего содержания:
3 (1,2) (2,3) (3,1.54) (2,5) (3,7) (4,10) (1.5,3.25) (1.7,-9.34) (6.23,11.17) (1.5,3.25) (1.7,-9.34) (6.23,11.17) (0.11,8.22) (0.34,-18.21) (1,-7) (1,5) (7,-13) (12,89)
Текст программы, реализующий поставленную задачу, представлен ниже.
#include <iostream>
#include <fstream>
#include <math.h>
#include <complex>
using namespace std;
//Решение СЛАУ с комплексными коэффициентами
int SLAU( complex <float > ** matrica_a, int n, complex <float > *massiv_b,
complex <float > *x )
{
int i, j, k, r;
complex <float > c,M, s;
float max;
complex <float > **a, *b;
a=new complex <float > *[ n ];
for ( i =0; i<n; i++)
a [ i ]=new complex <float >[n ];
b=new complex <float > [ n ];
for ( i =0; i<n; i++)
for ( j =0; j<n; j++)
a [ i ] [ j ]=matrica_a [ i ] [ j ];
for ( i =0; i<n; i++)
b [ i ]=massiv_b [ i ];
for ( k=0;k<n; k++)
{
max= abs ( a [ k ] [ k ] );
r=k;
for ( i=k+1; i<n; i++)
if ( abs ( a [ i ] [ k ] )>max)
{
max=abs ( a [ i ] [ k ] );
r= i;
}
for ( j =0; j<n; j++)
{
c=a [ k ] [ j ];
a [ k ] [ j ]=a [ r ] [ j ];
a [ r ] [ j ]= c;
}
c=b [ k ];
b [ k ]=b [ r ];
b [ r ]= c;
for ( i=k+1; i<n; i++)
{
for (M=a [ i ] [ k ] / a [ k ] [ k ], j=k; j<n; j++)
a [ i ] [ j ]_=M_a [ k ] [ j ];
b [ i ]-=M*b [ k ];
}
}
if ( abs ( a [ n -1 ] [ n-1 ])==0)
if ( abs ( b [ n-1 ])==0)
return -1;
else return -2;
else
{
for ( i=n-1; i >=0; i --)
{
for ( s =0, j= i +1; j<n; j++)
s+=a [ i ] [ j ] * x [ j ];
x [ i ]=( b [ i ]- s ) /a [ i ] [ i ];
}
return 0;
}
for ( i =0; i<n; i++)
delete [ ] a [ i ];
delete [ ] a;
delete [ ] b;
}
//Вычисление обратной матрицы с комплексными коэффициентами
int INVERSE( complex <float > **a, int n, complex <float > **y )
{
int i, j, res;
complex <float > *b, *x;
b=new complex <float > [ n ];
x=new complex <float > [ n ];
for ( i =0; i<n; i++)
{
for ( j =0; j<n; j++)
if ( j==i )
b [ j ]= 1;
else b [ j ]= 0;
res=SLAU( a, n, b, x );
if ( res !=0)
break;
else
for ( j =0; j<n; j++)
y [ j ] [ i ]=x [ j ];
}
delete [ ] x;
delete [ ] b;
if ( res !=0)
return -1;
else
return 0;
}
//Вычисление определителя матрицы с комплексными коэффициентами
complex <float > determinant ( complex <float > ** matrica_a, int n )
{
int i, j, k, r;
complex <float > c,M, s, det =1;
complex <float > **a;
float max;
a=new complex <float > * [ n ];
for ( i =0; i<n; i++)
a [ i ]=new complex <float >[n ];
for ( i =0; i<n; i++)
for ( j =0; j<n; j++)
a [ i ] [ j ]=matrica_a [ i ] [ j ];
for ( k=0;k<n; k++)
{
max=abs ( a [ k ] [ k ] );
r=k;
for ( i=k+1; i<n; i++)
if ( abs ( a [ i ] [ k ] )>max)
{
max=abs ( a [ i ] [ k ] );
r= i;
}
if ( r !=k ) det=-det;
for ( j =0; j<n; j++)
{
c=a [ k ] [ j ];
a [ k ] [ j ]=a [ r ] [ j ];
a [ r ] [ j ]= c;
}
for ( i=k+1; i<n; i++)
for (M=a [ i ] [ k ] / a [ k ] [ k ], j=k; j<n; j++)
a [ i ] [ j ]-=M*a [ k ] [ j ];
}
for ( i =0; i<n; i++)
det*=a [ i ] [ i ];
return det;
for ( i =0; i<n; i++)
delete [ ] a [ i ];
delete [ ] a;
}
//Умножение матриц с комплексными коэффициентами
void umn ( complex <float > **a, complex <float > **b, complex <float > **c, int
n, int m, int k )
{
int i, j, p;
for ( i =0; i<n; i++)
for ( j =0; j<k; j++)
for ( c [ i ] [ j ]=p=0;p<m; p++)
c [ i ] [ j ]+=a [ i ] [ p ] * b [ p ] [ j ];
}
int main ( )
{
int i, j,N;
complex <float > **A, **B, **X, **Y;
ifstream f;
ofstream g;
f.open ( " abc2.txt " );
f>>N;
cout<<" N = "<<N<<endl;
A=new complex <float > * [N ];
for ( i =0; i<N; i++)
A [ i ]=new complex <float > [N ];
B=new complex <float > * [N ];
for ( i =0; i<N; i++)
B [ i ]=new complex <float > [N ];
X=new complex <float > * [N ];
for ( i =0; i<N; i++)
X [ i ]=new complex <float > [N ];
Y=new complex <float > * [N ];
for ( i =0; i<N; i++)
Y [ i ]=new complex <float > [N ];
for ( i =0; i<N; i++)
for ( j =0; j<N; j++)
f>>A [ i ] [ j ];
cout<<"Матрица A\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<N; j++)
cout<<A [ i ] [ j ]<<" \t ";
for ( i =0; i<N; i++)
for ( j =0; j<N; j++)
f>>B [ i ] [ j ];
cout<<"Матрица B\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<N; j++)
cout<<B [ i ] [ j ]<<" \t ";
if ( ! INVERSE(A, N, X) )
{
cout<<"Обратная матрица\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<N; j++)
cout<<X [ i ] [ j ]<<" \t ";
umn(X, B,Y,N,N,N);
cout<<" \n Решение матричного уравнения \n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<N; j++)
cout<<Y [ i ] [ j ]<<" \t ";
}
else cout<<"Не существует обратной матрицы\n ";
cout<<"Определитель= "<<determinant (A,N);
return 0;
}
Результат работы программы к задаче 9.5:
N=3 Матрица A (1,2) (2,3) (3,1.54) (2,5) (3,7) (4,10) (1.5,3.25) (1.7,-9.34) (6.23,11.17) Матрица B (1.5,3.25) (1.7,-9.34) (6.23,11.17) (0.11,8.22) (0.34,-18.21) (1,-7) (1,5) (7,-13) (12,89) Обратная матрица (-0.495047,-0.748993) (0.325573,0.182901) (-0.0340879,-0.0958618) (0.125154,0.0765918) (-0.058179,-0.0728342) (0.00208664,0.0685887) (0.157733,0.322512) (-0.0859214,-0.127174) (0.0143863,-0.000518244) Определитель=(7.50219,-208.261) Решение матричного уравнения (0.669246,-0.302366) (-5.88068,-2.74393) (15.0106,-16.4762) (0.190248,0.114415) (0.488295,0.448942) (-6.72319,3.21833) (0.241332,0.347549) (1.02932,0.405788) (-3.37716,5.51956)
Разработать программу на языке C++ для решения следующей задачи. Даны комплексные числа $$a=\alpha+\beta\cdot i,\ b=\gamma+\delta\cdot i$$ и $$c=\lambda+\mu\cdot i$$. Найти комплесное число $$d=\varphi+\psi\cdot i$$ по формуле, представленной в табл. 9.2.
| Вариант | Формула для вычислений |
|---|---|
| 1 | $$d=a^2\cdot \frac{a+b}{a-b\cdot c}$$ |
| 2 | $$d=a^2\cdot \frac{(a+b-c)}{b}$$ |
| 3 | $$d=\frac{a^3\cdot b}{b+c}\cdot \left|a-b\right|$$ |
| 4 | $$d=(a-c)^2\cdot \frac{(a+b)}{a}$$ |
| 5 | $$d=\frac{a^2\cdot b}{a+c}\cdot (a-b)$$ |
| 6 | $$d=(a+c)^2\cdot {\frac{(a-b)}{(a-c)}}$$ |
| 7 | $$d=\frac{a\cdot b^2+c}{a-b}$$ |
| 8 | $$d=(a+b-c)^2\cdot {\frac{b}{a}}$$ |
| 9 | $$d=\frac{a\cdot b^3-c}{a+b}$$ |
| 10 | $$d=(a+b-c)\cdot {\frac{b^2}{c}}$$ |
| 11 | $$d=\frac{a^3\cdot b+c}{a-b}$$ |
| 12 | $$d=\frac{(a^2+b-c^3)}{a}$$ |
| 13 | $$d=\frac{a+b^2-c}{a+b+c}$$ |
| 14 | $$d=\frac{(a+b^2-c)}{(a+b^2)}$$ |
| 15 | $$d=\left(\frac{a+b+c}{a-b+c}\right)^2$$ |
| 16 | $$d=(a-b-c)\cdot {\frac{(b+c)}{(b-c)}}$$ |
| 17 | $$d=\left(\frac{a+b^3+c}{a-b^2-c}\right)$$ |
| 18 | $$d=(a+b+c)\cdot {\frac{(b-a)}{(b-c)}}$$ |
| 19 | $$d=\left(\frac{a-b-c}{a-b^2+c^3}\right)$$ |
| 20 | $$d=\frac{(a^2-b+c)}{(b-c^3)}$$ |
| 21 | $$d=\frac{(a+b+c)^2}{a-b-c}$$ |
| 22 | $$d=(a+b+c)\cdot {\frac{(b+c)^2}{(b-c)^3}}$$ |
| 23 | $$d=\frac{\left(a^2+b-c\right)\cdot a}{b}$$ |
| 24 | $$d=\frac{(\frac{b}{c}+b\cdot c)}{(a-c)}$$ |
| 25 | $$d=(a^2-\frac{b}{c})\cdot {\frac{(a+c)}{(a-c)}}$$ |
Разработать программу на языке C++ для решения следующей задачи:
Из предыдущих глав известно, что массив это переменная для хранения множества данных одного типа. Если возникает необходимость обрабатывать разнородную информацию как единое целое, то применяют тип данных структуры. Он позволяет сгруппировать объекты различных типов данных под одним именем.
Для того, чтобы объявить переменные структурного типа, вначале нужно задать новый тип данных, указав имя структуры и её элементы. Элементы структуры называются полями, и могут иметь любой тип данных кроме типа этой же структуры. Далее приведён пример создания структурного типа student, полями которого являются фамилия студента, шифр группы, год начала обучения и оценки по четырём предметам:
struct student
{
//Поля структуры:
char fio [ 30 ];
char group [ 8 ];
int year;
int informatika, math, fizika, history;
}
На основании созданного структурного типа данных можно описать переменные типа student:
student Vasya; //Переменная Vasya типа student. student ES [ 50 ]; //Массив, элементы которого имеют тип student. student *x; //Указатель на тип данных student
Обращаются к полям переменной структурного типа так:
имя_структуры.поле
Например,
Vasya.year; //Обращение к полю year переменной Vasya. ES[4].math; //Обращение к полю math элемента ES[4].
Задача 9.1. Задано $$n$$ комплексных чисел, которые хранятся в двоичном файле. Найти значение наибольшего модуля среди заданных чисел.
Напомним, что комплексные числа это числа вида $$z=a+b\cdot i$$, где $$a$$ и $$b$$ — действительные числа, а $$i$$ — мнимая единица, $$i^2=-1$$. Комплексное число расширяет понятие действительного числа. Если действительное число — это любая точка на числовой прямой, то под комплексным числом понимают точку на плоскости (рис. 9.1). Модуль комплексного числа $$z$$ вычисляют по формуле $$|z|=\sqrt{a^2+b^2}$$.
Для решения задачи 9.1 разработаны две программы. Первая создаёт файл исходных данных, вторая получает из него информацию и обрабатывает её в соответствии с поставленной задачей.
Далее приведён текст программы создания двоичного файла с $$n$$ комплексными числами. В файл complex.dat будет записано число n, а затем последовательно комплексные числа.
#include <iostream>
#include <fstream>
using namespace std;
int main ( )
{
//Структура Комплексное число.
struct complex
{
//Поля структуры:
double Re; //Действительная часть.
double Im; //Мнимая часть.
};
complex p; //Переменная для хранения комплексного чисела.
int i, n;
FILE *f;
cout<<" n = "; cin>>n;
f=fopen ( " complex.dat ", " wb " );
fwrite (n, sizeof ( int ), 1, f );
for ( i =0; i<n; i++)
{
cout<<"Введите комплексное число\n ";
//Ввод комплексного числа:
cin>>p.Re; //действительная часть,
cin>>p.Im; //мнимая часть.
//Вывод комплексного числа.
cout<<p.Re<<" + "<<p.Im<<" i "<<endl;
//Запись комплексного числа в двоичный файл.
fwrite (p, sizeof ( complex ), 1, f );
}
fclose ( f );
return 0;
}
(рис 9.1) Геометрическая модель комплексного числа a + b · i
(рис 9.2) Геометрическая интерпретация комплексно-сопряжённого числа
Следующая программа считывает информацию из файла complex.dat — количество комплексных чисел в переменную n, а сами комплексные числа в массив p. Затем происходит поиск комплексного числа с максимальным модулем в массиве p.
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{
struct complex
{
double Re;
double Im;
};
complex *p;
int i, n, nmax;
double max;
FILE *f;
f=fopen ( " complex.dat ", " rb " );
fread (n, sizeof ( int ), 1, f );
p=new complex [ n ];
fread ( p, sizeof ( complex ), n, f );
//Поиск комплексного числа с максимальным модулем
max=sqrt ( p[0].Re*p[0].Re+p[0].Im*p[0].Im );
for ( i =1,nmax=0; i<n; i++)
if ( sqrt ( p[i].Re*p[i].Re+p[i].Im*p[i].Im )>max)
{
max=sqrt ( p[i].Re*p[i].Re+p [i].Im*p[i].Im );
nmax= i;
}
cout<<" max = "<<max<<" \t nmax = "<<nmax<<endl;
fclose ( f );
return 0;
}
Задача 9.2. Даны два комплексных числа $$z_1$$ и $$z_2$$. Выполнить над ними основные операции:
Суммой двух комплексных чисел $$z_1=a+i\cdot b$$ и $$z_2=c+i\cdot d$$ называется комплексное число $$z=z_1+z_2=(a+c)+i\cdot (b+d)$$.
Разностью двух комплексных чисел $$z_1=a+i\cdot b$$ и $$z_2=c+i\cdot d$$ называется комплексное число $$z=z_1-z_2=(a-c)+i\cdot (b-d)$$.
Произведением двух комплексных чисел $$z_1=a+i\cdot b$$ и $$z_2=c+i\cdot d$$ называется комплексное число $$z=z_1\cdot {z_2}=(a\cdot c-b\cdot d)+i\cdot (b\cdot c+a\cdot d)$$.
Частным двух комплексных чисел $$z_1=a+i\cdot b$$ и $$z_2=c+i\cdot d$$ называется комплексное число $$z=\frac{z_1}{z_2}=\frac{ac+bd}{c^2+d^2}+i\cdot {\frac{bc-ad}{c^2+d^2}}$$ Числом, сопряжённым комплексному числу $$z=x+i\cdot y$$, называется число $$\bar{z}=x-i\cdot y$$ (рис. 9.2).
Всякое комплексное число, записанное в алгебраической форме $$z=x+i\cdot y$$, можно записать в тригонометрической $$z=r(\cos \phi+i\cdot \sin \phi)$$ или в показательной форме $$z=r\cdot e^{i\cdot \phi}$$, где $$r=\sqrt{x^2+y^2}$$ — модуль комплексного числа $$z,\ \phi=\arctan \frac{y}{x}$$— его аргумент (рис. 9.2).
Для возведения в степень комплексного числа, записанного в тригонометрической форме $$z=r(\cos\phi+i\cdot \sin \phi$$), можно воспользоваться формулой Муавра $$z^n=r^n\cdot (\cos (n\cdot \phi)+i\cdot \sin (n\cdot \phi)).$$ Формула для извлечения корня $$n$$-й степени из комплексного числа $$z=r\cdot (\cos \phi+i\cdot \sin \phi)$$ имеет вид $$\sqrt[n]z=\sqrt[n]z(\cos \frac{\phi+2\cdot \pi \cdot k}{n}+i\cdot \sin \frac{\phi+2\cdot \pi \cdot k}{n}),$$ где $$n>1,k=0,1,\dots,n-1$$.
Далее приведён текст программы, реализующий алгоритм решения задачи 9.2. В программе описаны две структуры для работы с комплексными числами: структура complex1 для представления комплексных чисел в алгебраической форме (Re — действительная часть комплексного числа, Im — его мнимая часть) и структура complex2 для представления комплексных чисел в показательной или тригонометрической форме (Modul — модуль комплексного числа, Argum — его аргумент). Кроме того в программе созданы функции, реализующие основные действия над комплексными числами, переход между различными формами представления комплексных чисел, а также ввод-вывод комплексных чисел.
#include <iostream>
#include <math.h>
using namespace std;
struct complex1
{
float Re;
float Im;
};
struct complex2
{
float Modul;
float Argum;
};
//Ввод числа в алгебраической форме
complex1 vvod1 ( )
{
complex1 temp;
cout<<"Введите действительную часть числа\n ";
cin>>temp.Re;
cout<<"Введите мнимую часть комплексного числа\n ";
cin>>temp.Im;
return temp;
}
//Ввод числа в тригонометрической или показательной форме
complex2 vvod2 ( )
{
complex2 temp;
cout<<"Введите модуль комплексного числа\n ";
cin>>temp.Modul;
cout<<"Введите аргумент комплексного числа\n ";
cin>>temp.Argum;
return temp;
}
//Вывод числа в алгебраической форме
void vivod ( complex1 chislo )
{
cout<<chislo.Re;
if ( chislo.Im>=0)
cout<<" + "<< chislo.Im<<" i "<<endl;
else
cout<<" "<< chislo.Im<<" i "<<endl;
}
//Вывод числа в тригонометрической форме
void vivod ( complex2 chislo )
{
cout<<chislo.Modul<<" ( cos ( "<< chislo.Argum<<" ) + i sin ( "<< chislo.Argum<<
" ) ) "<<endl;
}
//Перевод числа из тригонометрической формы в алгебраическую,
//pr определяет, выводить или нет полученное число на экран.
complex1 perevod ( complex2 chislo, bool pr=false )
{
complex1 temp;
temp.Re=chislo.Modul*cos ( chislo.Argum );
temp.Im=chislo.Modul*sin ( chislo.Argum );
if ( pr ) vivod ( temp );
return temp;
}
//Перевод числа из алгебраической формы в тригонометрическую,
//pr определяет, выводить или нет полученное число на экран.
complex2 perevod ( complex1 chislo, bool pr=false )
{
complex2 temp;
temp.Modul=sqrt ( chislo.Re* chislo.Re+
chislo.Im*chislo.Im );
temp.Argum=atan ( chislo.Im/ chislo.Re );
if ( pr ) vivod ( temp );
return temp;
}
//Функция сложения двух чисел в алгебраической форме,
//pr определяет, выводить или нет число на экран.
complex1 plus1 ( complex1 chislo1, complex1 chislo2, bool pr=true )
{
complex1 temp;
temp.Re=chislo1.Re+chislo2.Re;
temp.Im=chislo1.Im+chislo2.Im;
if ( pr ) vivod ( temp );
return temp;
}
//Функция вычитания двух чисел в алгебраической форме,
//pr определяет, выводить или нет число на экран.
complex1 minus1 ( complex1 chislo1, complex1 chislo2, bool pr=true )
{
complex1 temp;
temp.Re=chislo1.Re-chislo2.Re;
temp.Im=chislo1.Im-chislo2.Im;
if ( pr ) vivod ( temp );
return temp;
}
//Функция умножения двух чисел в алгебраической форме,
//pr определяет, выводить или нет число на экран.
complex1 mult1 ( complex1 chislo1, complex1 chislo2, bool pr=true )
{
complex1 temp;
temp.Re=chislo1.Re* chislo2.Re-chislo1.Im* chislo2.Im;
temp.Im=chislo1.Im* chislo2.Re+chislo1.Re* chislo2.Im;
if ( pr ) vivod ( temp );
return temp;
}
//Функция деления двух чисел в алгебраической форме,
//pr определяет, выводить или нет число на экран.
complex1 divide1 ( complex1 chislo1, complex1 chislo2, bool pr=true )
{
complex1 temp;
temp.Re=( chislo1.Re* chislo2.Re+chislo1.Im* chislo2.Im ) / ( chislo2.Re* chislo2 .
Re+chislo2.Im* chislo2.Im );
temp.Im=( chislo1.Im* chislo2.Re-chislo1.Re* chislo2.Im ) / ( chislo2.Re* chislo2 .
Re+chislo2.Im* chislo2.Im );
if ( pr ) vivod ( temp );
return temp;
}
//Функция возведения комплексного числа в алгебраической форме
//в целую степень n, pr определяет, выводить или нет полученное число на экран.
complex1 pow1 ( complex1 chislo1, int n, bool pr=true )
{
complex1 temp;
complex2 temp2;
float p=1;
int i =1;
temp2=perevod ( chislo1, true ); //Перевод числа в тригонометрическую форму.
for (; i<=n; p*=temp2.Modul, i++);
temp.Re=p*cos ( n*temp2.Argum );
temp.Im=p*sin ( n*temp2.Argum );
if ( pr ) vivod ( temp );
return temp;
}
//Функция извлечения корня степени n из комплексного числа
//в алгебраической форме, pr определяет, выводить или нет
//полученные значения на экран. Функция возвращает ro и fi.
void sqrt n 1 ( complex1 chislo1, int n, float _ ro, float _ f i, bool pr=true )
{
complex1 temp;
complex2 temp2;
int i =0;
temp2=perevod ( chislo1, true ); //Перевод числа в тригонометрическую форму.
* r o=pow ( temp2.Modul, ( float ) 1/n );
* f i=temp2.Argum;
if ( pr )
{
for ( i =0; i<n; i++)
{
cout<<i<<"-е значение корня\n ";
temp.Re=*ro* cos ( ( * fi +2*M_PI* i ) /n );
temp.Im=*ro* sin ( ( * fi +2*M_PI* i ) /n );
vivod ( temp );
}
}
}
int main ( )
{
complex1 chislo1, chislo2; //Описание комплексных
complex1 chislo5; //чисел в алгебраической форме.
complex2 chislo3, chislo4; //Описание комплексных чисел в тригонометрической форме.
float ro1, fi1;
chislo1=vvod1 ( ); //Ввод исходных данных
chislo2=vvod1 ( ); //в алгебраической форме.
vivod ( chislo1 ); //Вывод исходных данных
vivod ( chislo2 ); //в алгебраической форме.
chislo 3=perevod ( chislo1, true ); //Перевод чисел
chislo 4=perevod ( chislo2, true ); //в тригонометрическую форму и вывод их на экран.
cout<<"Сумма чисел ";
chislo5=plus1 ( chislo1, chislo2, true );
cout<<"Разность чисел ";
chislo5=minus1 ( chislo1, chislo2, true );
cout<<"Произведение чисел ";
chislo5=mult1 ( chislo1, chislo2, true );
cout<<"Частное чисел ";
chislo5=divide1 ( chislo1, chislo2, true );
chislo5=pow1 ( chislo1, 5, true ); //Возведение числа в пятую степень.
sqrtn1 ( chislo1, 5, Ro1, fi1, true ); //Извлечение корня пятой степени.
return 0;
}
Результаты работы программы к задаче 9.2.
Введите действительную часть числа 5 Введите мнимую часть комплексного числа -7 Введите действительную часть числа 11 Введите мнимую часть комплексного числа 1.85 5 -7 i 11 +1.85 i 8.60233 ( cos (-0.950547) + i sin (-0.950547)) 11.1545 ( cos (0.166623) + i sin (0.166623)) Сумма чисел 16 -5.15 i Разность чисел -6 -8.85 i Произведение чисел 67.95 -67.75 i Частное чисел 0.337961 -0.693203 i 8.60233 ( cos (-0.950547) + i sin (-0.950547)) 1900 +47068 i 8.60233 ( cos (-0.950547) + i sin (-0.950547)) 0-е значение корня 1.51018 -0.290608 i 1-е значение корня 0.743054 +1.34646 i 2-е значение корня -1.05094 +1.12277 i 3-е значение корня -1.39257 -0.652552 i 4-е значение корня 0.190285 -1.52606 i
Работа с комплексными числами в C++ реализована с помощью библиотеки complex. Подключение этой библиотеки даёт возможность применять операции +, _, *, / для работы не только с вещественными, но и с комплексными числами.
Перед подключением библиотеки complex обязательно необходимо подключить библиотеку math.h.
Для определения переменной типа комплексное число используется оператор.
complex <тип_переменной> имя_переменной;
Здесь тип_переменной — это любой допустимый в C++ числовой тип данных (int, long int, double, float и т. д.), описывающий действительную и мнимую части комплексного числа. Например,
complex <float > x, y, z [ 5 ], * r; complex <double> a; complex <int> a, b, c;
Для организации ввода-вывода комплексных чисел можно использовать библиотеку iostream и стандартные конструкции cin, cout. Например,
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
int main ( int arg c, char ** argv )
{
complex <double> b, c; //Описание комплексных чисел.
cout<<" b = "; cin>>b; //Ввод комплексного числа b.
cout<<" c = "; cin>>c; //Ввод комплексного числа c.
cout<<" b / c = "<<b/ c; //Вывод частного комплексных чисел
return 0;
}
В результате получим:
b=(1.24,-6.12) c=(9.01,-11.22) b/c=(0.385567,-0.199105)
Обратите внимание, что при вводе комплексных чисел с клавиатуры действительная и мнимая части вводятся в скобках через запятую:
(действительная_часть, мнимая_часть)
Далее приведён пример присваивания комплексным переменным реальных значений при их описании:
complex <double> z ( 4.0, 1.0 ); complex <int> r ( 4, -7);
Следующий пример демонстрирует, как из двух числовых значений можно составить комплексное число:
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
int main ( int arg c, char ** argv )
{
double x1, y1;
x1=-2.3;
y1 = 8.1;
complex <double> b ( x1, y1 ); //Формирование комплексного числа b
//с действительной частью x1 и мнимой y1.
cout<<" b ^ 2 = "<<b*b; //Вывод квадрата комплексного числа.
return 0;
}
В табл. 9.1 представлены основные математические функции для работы с комплексными числами.
| Прототип функции | Описание функции |
|---|---|
double abs(complex z) |
Возвращает модуль комплексного числа $$z$$. |
double arg(complex z) |
Возвращает значение аргумента комплексного числа $$z$$ |
complex conj(complex z) |
Возвращает число комплексно сопряжённое числу $$z$$ |
complex cos(complex z) |
Возвращает косинус комплексного числа $$z$$ |
complex cosh(complex z) |
Возвращает гиперболический косинус комплексного числа $$z$$. |
complex exp(complex z) |
Возвращает экспоненту комплексного числа $$z$$. |
double imag(complex z) |
Возвращает мнимую часть комплексного числа $$z$$. |
complex log(complex z) |
Возвращает натуральный логарифм комплексного числа $$z$$ |
complex log10(complex z) |
Возвращает десятичный логарифм комплексного числа $$z$$. |
double norm(complex z) |
Возвращает квадрат модуля комплексного числа $$z$$. |
complex pow(complex x, complex y) |
Возвращает степень комплексного числа $$z$$. |
complex polar(double mag, double angle) |
Формирует комплексное число с модулем $$mag$$ и аргументом $$angle.$$ |
double real(complex z) |
Возвращает действительную часть комплексного числа $$z$$ |
complex sin(complex z) |
Возвращает синус комплексного числа $$z$$ |
complex sinh(complex z) |
Возвращает гиперболический синус комплексного числа $$z$$. |
complex sqrt(complex z) |
Возвращает квадратный корень комплексного числа $$z$$ |
complex tan(complex z) |
Возвращает тангенс комплексного числа $$z$$ |
complex tanh(complex z) |
Возвращает гиперболический тангенс комплексного числа $$z$$. |
Далее приведён текст программы, демонстрирующий работу с некоторыми функциями из табл. 9.1.
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
int main ( )
{
complex <double> x ( 4, -6);
complex <double> y (-7, 2 );
cout<<" x * y = "<<x*y<<endl;
cout<<" sin ( x ) * cos ( y ) = "<<sin ( x ) * cos ( y )<<endl;
cout<<" conj ( x ) * ln ( y ) = "<<conj ( x ) * log ( y )<<endl;
cout<<" sh ( y ) = "<<sinh ( y )<<endl;
return 0;
}
Результаты работы программы с некоторыми функциями комплексного аргумента:
x*y=(-16,50) sin(x)*cos(y)=(-747.159,10.2102) conj(x)*ln(y)=(-9.23917,23.364) sh(y)=(228.18,498.583)
Задача 9.3. Вычислить $$y={(\sqrt{3}-i)}^{20},\ z=\left(\frac{1+i\cdot \sqrt{3}}{1-i}\right)^{40}$$.
Если провести аналитические преобразования, то получим следующее:
$$y=2^{19}\cdot (-1+i\cdot \sqrt{3}),\ z=-2^{19}\cdot (1+i\cdot \sqrt{3}).$$Проверим эти вычисления с помощью программы на C++. Результаты работы программы подтверждают аналитические вычисления.
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
int main ( )
{
complex <double> b ( sqrt ( 3 ),-1), y;
y=pow ( b, 20 );
cout<<" y = "<<y<<endl;
cout<<real ( y ) /pow ( 2, 1 9 )<<" \t ";
cout<<imag ( y ) /pow ( 2, 1 9 )<<" \n ";
complex <double> a ( 1, sqrt ( 3 ) ), c (1, -1), z;
z=pow ( a / c, 40 );
cout<<" z = "<<z<<endl;
cout<<real ( z ) /pow ( 2, 19 )<<" \t ";
cout<<imag ( z ) /pow ( 2, 19 )<<" \n ";
return 0;
}
Результаты работы программы к задаче 9.3:
b=(1.73205,-1)y=(-524288,908093) -1 1.73205 z=(-524288,-908093) -1 -1.73205
Операции с массивами, элементами которых являются комплексные числа, осуществляются так же, как и с обычными переменными. В качестве примера рассмотрим следующие задачи.
Задача 9.4. Написать программу умножения матриц комплексных чисел. Матрицы $$A$$ и $$B$$ имеют вид:
$$A=\left(\begin{array}{rrrr}1+2\cdot i2+3\cdot i3+1.54\cdot i4-7.2\cdot i\\2+5\cdot i3+7\cdot i4+10\cdot i5+14\cdot i\\1.5+3.25\cdot i1.7-3.94\cdot i6.23+11.17\cdot i-4.12+3.62\cdot i\end{array}\right), \noindent B=\left(\begin{array}{rrrrr}6.23-1.97\cdot i0.19+0.22\cdot i0.16+0.28\cdot i3.4+1.95\cdot i2.20-0.18\cdot i\\0.22+0.29\cdot i11+12\cdot i6.72-1.13\cdot i16+18\cdot i34+66\cdot i\\5+1\cdot i1.4-1.76\cdot i4.5+2.3\cdot i296+700\cdot i4.2+1.03\cdot i\\-3.4-2.61\cdot i1+11\cdot i2+23\cdot i3-35\cdot i4+47\cdot i\end{array}\right).$$Пусть исходные данные хранятся в файле abc.txt. Данные к задаче 9.4, содержимое файла abc.txt:
3 4 5 (1,2) (2,3) (3,1.54) (4,-7.2) (2,5) (3,7) (4,10) (5,14) (1.5,3.25) (1.7,-3.94) (6.23,11.17) (-4.12,3.62) (6.23,-1.97) (0.19,0.22) (0.16,0.28) (3.4,1.95) (2.20,-0.18) (0.22,0.29) (11,12) (6.72,-1.13) (16,18) (34,66) (5,1) (1.4,-1.76) (4.5,2.3) (296,700) (4.2,1.03) (-3.14,-2.61) (1,11) (2,23) (3,-35) (4,47)
Далее приведён текст программы, реализующий алгоритм решения задачи 9.4.
#include <iostream>
#include <fstream>
#include <math.h>
#include <complex>
using namespace std;
int main ( )
{
int i, j, p,N,M,K;
complex <float > **A, **B, **C;
ifstream f;
ofstream g;
f.open ( " abc.txt " );
f>>N>>M>>K;
cout<<" N = "<<N<<" \tM = "<<M<<" \tK = "<<K<<endl;
A=new complex <float > * [N ];
for ( i =0; i<N;A [ i ]=new complex <float > [M], i++);
B=new complex <float > * [M];
for ( i =0; i<M;B [ i ]=new complex <float > [K ], i++);
C=new complex <float > * [N ];
for ( i =0; i<N;C [ i ]=new complex <float > [K ], i++);
for ( i =0; i<N; i++)
for ( j =0; j<M; f>>A [ i ] [ j ], j++);
cout<<"Матрица A\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<M; cout<<A [ i ] [ j ]<<" \t ", j++);
for ( i =0; i<M; i++)
for ( j =0; j<K; f>>B [ i ] [ j ], j++);
cout<<"Матрица B\n ";
for ( i =0; i<M; cout<<endl, i++)
for ( j =0; j<K; cout<<B [ i ] [ j ]<<" \t ", j++);
for ( i =0; i<N; i++)
for ( j =0; j<K; j++)
for (C [ i ] [ j ]=p=0;p<M; p++)
C [ i ] [ j ]+=A [ i ] [ p ] *B [ p ] [ j ];
f.close ( );
cout<<"Матрица C\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<K; cout<<C [ i ] [ j ]<<" \t ", j++);
g.open ( " result.t x t " );
g<<"Матрица C=A*B\n ";
for ( i =0; i<N; g<<endl, i++)
for ( j =0; j<K; g<<C [ i ] [ j ]<<" \t ", j++);
g.close ( );
return 0;
}
Результат умножения матриц из задачи 9.4 (файл result.txt):
Матрица C=A*B (-8.152,34.598) (75.8604,91.276) (199.988,109.93) (-452.5,2486.99) (237.974,406.978) (51.78,26.61) (-177.52,190.35) (-290.01,242.21) (-5391.95,5813.9) (-986.2,783.76) (59.6291,78.3851) (49.9912,-59.0193) (-82.8542,-50.3838) (-5763.7,7803.92) (149.766,-140.709)
Задача 9.5. Заданы матрицы $$A$$ и $$B$$. Необходимо вычислить матрицу $$A^{-1}$$, обратную к матрице $$A$$, найти определитель $$|A|$$ матрицы $$A$$ и решить матричное уравнение $$A\cdot X=B$$, где $$X=A^{-1}\cdot B$$. Матрицы $$A$$ и $$B$$ имеют вид:
$$A=\left(\begin{array}{rrr}1+2\cdot i2+3\cdot i3+1.54\cdot i\\2+5\cdot i3+7\cdot i4+10\cdot i\\1.5+3.25\cdot i1.7-3.94\cdot i6.23+11.17\cdot i\end{array}\right), B=\left(\begin{array}{rrr}1.5+3.25\cdot i1.7-9.34\cdot i6.23+11.17\cdot i\\0.11+8.22\cdot i0.34-18.21\cdot i1-7\cdot i\\1+5\cdot i7-13\cdot i12+89\cdot i\end{array}\right).$$Для хранения исходных данных создадим текстовый файл abc2.txt следующего содержания:
3 (1,2) (2,3) (3,1.54) (2,5) (3,7) (4,10) (1.5,3.25) (1.7,-9.34) (6.23,11.17) (1.5,3.25) (1.7,-9.34) (6.23,11.17) (0.11,8.22) (0.34,-18.21) (1,-7) (1,5) (7,-13) (12,89)
Текст программы, реализующий поставленную задачу, представлен ниже.
#include <iostream>
#include <fstream>
#include <math.h>
#include <complex>
using namespace std;
//Решение СЛАУ с комплексными коэффициентами
int SLAU( complex <float > ** matrica_a, int n, complex <float > *massiv_b,
complex <float > *x )
{
int i, j, k, r;
complex <float > c,M, s;
float max;
complex <float > **a, *b;
a=new complex <float > *[ n ];
for ( i =0; i<n; i++)
a [ i ]=new complex <float >[n ];
b=new complex <float > [ n ];
for ( i =0; i<n; i++)
for ( j =0; j<n; j++)
a [ i ] [ j ]=matrica_a [ i ] [ j ];
for ( i =0; i<n; i++)
b [ i ]=massiv_b [ i ];
for ( k=0;k<n; k++)
{
max= abs ( a [ k ] [ k ] );
r=k;
for ( i=k+1; i<n; i++)
if ( abs ( a [ i ] [ k ] )>max)
{
max=abs ( a [ i ] [ k ] );
r= i;
}
for ( j =0; j<n; j++)
{
c=a [ k ] [ j ];
a [ k ] [ j ]=a [ r ] [ j ];
a [ r ] [ j ]= c;
}
c=b [ k ];
b [ k ]=b [ r ];
b [ r ]= c;
for ( i=k+1; i<n; i++)
{
for (M=a [ i ] [ k ] / a [ k ] [ k ], j=k; j<n; j++)
a [ i ] [ j ]_=M_a [ k ] [ j ];
b [ i ]-=M*b [ k ];
}
}
if ( abs ( a [ n -1 ] [ n-1 ])==0)
if ( abs ( b [ n-1 ])==0)
return -1;
else return -2;
else
{
for ( i=n-1; i >=0; i --)
{
for ( s =0, j= i +1; j<n; j++)
s+=a [ i ] [ j ] * x [ j ];
x [ i ]=( b [ i ]- s ) /a [ i ] [ i ];
}
return 0;
}
for ( i =0; i<n; i++)
delete [ ] a [ i ];
delete [ ] a;
delete [ ] b;
}
//Вычисление обратной матрицы с комплексными коэффициентами
int INVERSE( complex <float > **a, int n, complex <float > **y )
{
int i, j, res;
complex <float > *b, *x;
b=new complex <float > [ n ];
x=new complex <float > [ n ];
for ( i =0; i<n; i++)
{
for ( j =0; j<n; j++)
if ( j==i )
b [ j ]= 1;
else b [ j ]= 0;
res=SLAU( a, n, b, x );
if ( res !=0)
break;
else
for ( j =0; j<n; j++)
y [ j ] [ i ]=x [ j ];
}
delete [ ] x;
delete [ ] b;
if ( res !=0)
return -1;
else
return 0;
}
//Вычисление определителя матрицы с комплексными коэффициентами
complex <float > determinant ( complex <float > ** matrica_a, int n )
{
int i, j, k, r;
complex <float > c,M, s, det =1;
complex <float > **a;
float max;
a=new complex <float > * [ n ];
for ( i =0; i<n; i++)
a [ i ]=new complex <float >[n ];
for ( i =0; i<n; i++)
for ( j =0; j<n; j++)
a [ i ] [ j ]=matrica_a [ i ] [ j ];
for ( k=0;k<n; k++)
{
max=abs ( a [ k ] [ k ] );
r=k;
for ( i=k+1; i<n; i++)
if ( abs ( a [ i ] [ k ] )>max)
{
max=abs ( a [ i ] [ k ] );
r= i;
}
if ( r !=k ) det=-det;
for ( j =0; j<n; j++)
{
c=a [ k ] [ j ];
a [ k ] [ j ]=a [ r ] [ j ];
a [ r ] [ j ]= c;
}
for ( i=k+1; i<n; i++)
for (M=a [ i ] [ k ] / a [ k ] [ k ], j=k; j<n; j++)
a [ i ] [ j ]-=M*a [ k ] [ j ];
}
for ( i =0; i<n; i++)
det*=a [ i ] [ i ];
return det;
for ( i =0; i<n; i++)
delete [ ] a [ i ];
delete [ ] a;
}
//Умножение матриц с комплексными коэффициентами
void umn ( complex <float > **a, complex <float > **b, complex <float > **c, int
n, int m, int k )
{
int i, j, p;
for ( i =0; i<n; i++)
for ( j =0; j<k; j++)
for ( c [ i ] [ j ]=p=0;p<m; p++)
c [ i ] [ j ]+=a [ i ] [ p ] * b [ p ] [ j ];
}
int main ( )
{
int i, j,N;
complex <float > **A, **B, **X, **Y;
ifstream f;
ofstream g;
f.open ( " abc2.txt " );
f>>N;
cout<<" N = "<<N<<endl;
A=new complex <float > * [N ];
for ( i =0; i<N; i++)
A [ i ]=new complex <float > [N ];
B=new complex <float > * [N ];
for ( i =0; i<N; i++)
B [ i ]=new complex <float > [N ];
X=new complex <float > * [N ];
for ( i =0; i<N; i++)
X [ i ]=new complex <float > [N ];
Y=new complex <float > * [N ];
for ( i =0; i<N; i++)
Y [ i ]=new complex <float > [N ];
for ( i =0; i<N; i++)
for ( j =0; j<N; j++)
f>>A [ i ] [ j ];
cout<<"Матрица A\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<N; j++)
cout<<A [ i ] [ j ]<<" \t ";
for ( i =0; i<N; i++)
for ( j =0; j<N; j++)
f>>B [ i ] [ j ];
cout<<"Матрица B\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<N; j++)
cout<<B [ i ] [ j ]<<" \t ";
if ( ! INVERSE(A, N, X) )
{
cout<<"Обратная матрица\n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<N; j++)
cout<<X [ i ] [ j ]<<" \t ";
umn(X, B,Y,N,N,N);
cout<<" \n Решение матричного уравнения \n ";
for ( i =0; i<N; cout<<endl, i++)
for ( j =0; j<N; j++)
cout<<Y [ i ] [ j ]<<" \t ";
}
else cout<<"Не существует обратной матрицы\n ";
cout<<"Определитель= "<<determinant (A,N);
return 0;
}
Результат работы программы к задаче 9.5:
N=3 Матрица A (1,2) (2,3) (3,1.54) (2,5) (3,7) (4,10) (1.5,3.25) (1.7,-9.34) (6.23,11.17) Матрица B (1.5,3.25) (1.7,-9.34) (6.23,11.17) (0.11,8.22) (0.34,-18.21) (1,-7) (1,5) (7,-13) (12,89) Обратная матрица (-0.495047,-0.748993) (0.325573,0.182901) (-0.0340879,-0.0958618) (0.125154,0.0765918) (-0.058179,-0.0728342) (0.00208664,0.0685887) (0.157733,0.322512) (-0.0859214,-0.127174) (0.0143863,-0.000518244) Определитель=(7.50219,-208.261) Решение матричного уравнения (0.669246,-0.302366) (-5.88068,-2.74393) (15.0106,-16.4762) (0.190248,0.114415) (0.488295,0.448942) (-6.72319,3.21833) (0.241332,0.347549) (1.02932,0.405788) (-3.37716,5.51956)
Разработать программу на языке C++ для решения следующей задачи. Даны комплексные числа $$a=\alpha+\beta\cdot i,\ b=\gamma+\delta\cdot i$$ и $$c=\lambda+\mu\cdot i$$. Найти комплесное число $$d=\varphi+\psi\cdot i$$ по формуле, представленной в табл. 9.2.
| Вариант | Формула для вычислений |
|---|---|
| 1 | $$d=a^2\cdot \frac{a+b}{a-b\cdot c}$$ |
| 2 | $$d=a^2\cdot \frac{(a+b-c)}{b}$$ |
| 3 | $$d=\frac{a^3\cdot b}{b+c}\cdot \left|a-b\right|$$ |
| 4 | $$d=(a-c)^2\cdot \frac{(a+b)}{a}$$ |
| 5 | $$d=\frac{a^2\cdot b}{a+c}\cdot (a-b)$$ |
| 6 | $$d=(a+c)^2\cdot {\frac{(a-b)}{(a-c)}}$$ |
| 7 | $$d=\frac{a\cdot b^2+c}{a-b}$$ |
| 8 | $$d=(a+b-c)^2\cdot {\frac{b}{a}}$$ |
| 9 | $$d=\frac{a\cdot b^3-c}{a+b}$$ |
| 10 | $$d=(a+b-c)\cdot {\frac{b^2}{c}}$$ |
| 11 | $$d=\frac{a^3\cdot b+c}{a-b}$$ |
| 12 | $$d=\frac{(a^2+b-c^3)}{a}$$ |
| 13 | $$d=\frac{a+b^2-c}{a+b+c}$$ |
| 14 | $$d=\frac{(a+b^2-c)}{(a+b^2)}$$ |
| 15 | $$d=\left(\frac{a+b+c}{a-b+c}\right)^2$$ |
| 16 | $$d=(a-b-c)\cdot {\frac{(b+c)}{(b-c)}}$$ |
| 17 | $$d=\left(\frac{a+b^3+c}{a-b^2-c}\right)$$ |
| 18 | $$d=(a+b+c)\cdot {\frac{(b-a)}{(b-c)}}$$ |
| 19 | $$d=\left(\frac{a-b-c}{a-b^2+c^3}\right)$$ |
| 20 | $$d=\frac{(a^2-b+c)}{(b-c^3)}$$ |
| 21 | $$d=\frac{(a+b+c)^2}{a-b-c}$$ |
| 22 | $$d=(a+b+c)\cdot {\frac{(b+c)^2}{(b-c)^3}}$$ |
| 23 | $$d=\frac{\left(a^2+b-c\right)\cdot a}{b}$$ |
| 24 | $$d=\frac{(\frac{b}{c}+b\cdot c)}{(a-c)}$$ |
| 25 | $$d=(a^2-\frac{b}{c})\cdot {\frac{(a+c)}{(a-c)}}$$ |
Разработать программу на языке C++ для решения следующей задачи:
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.