Программа 53. Комплексные числа

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

Назовем модуль для класса комплексных чисел UnComplex. В файле
UnComplex.h разместим объявление класса комплексных чисел:

// Файл UnComplex.h

#ifndef UnComplexH

#define UnComplexH

#include <math.h>

class Complex

{ // Данные класса

double re, im; // Действительная и мнимая части комплексного числа

public: // Методы класса

Complex() // Конструктор по умолчанию

{ re = 0; im = 0; }

Complex(double x) // Конструктор с одним аргументом, формирование

{ re = x; im = 0; } // комплексного числа по одному вещественному

Complex(double x, double y) // Конструктор с двумя аргументами

{ re = x; im = y; }

double Arg(); // Аргумент комплексного числа

double Abs(); // Модуль комплексного числа

Complex& operator+=(Complex z) // Сложение с присваиванием

{

re += z.re; im += z.im; return *this;

}

Complex& operator-=(Complex z) // Вычитание с присваиванием

{

re -= z.re; im -= z.im; return *this;

}

Complex operator*(Complex); // Перемножение комплексных чисел

Complex operator*(double);// Умножение комплексного на вещественное

Complex operator/(Complex); // Деление комплексных чисел

Complex operator-(); // Унарный минус

void Roots(int m, Complex* rts); // Извлечение корней степени m

void Print(); // Вывод комплексного числа

};

// Объявление функций, не являющихся членами класса Complex

Complex operator+(Complex z, Complex t); // Сложение

Complex operator-(Complex z, Complex t); // Вычитание

Complex operator*(double a, Complex z); // Умножение

Complex Pow(Complex z, int m); //Возведение комплексного в степень m

// Получение комплексного числа по его модулю и аргументу

Complex Polar(double mod, double arg);

#endif

В классе Complex предусмотрены три конструктора, чтобы можно было создавать комплексные числа любым из следующих способов:

Complex z1(1, 2); // z1.re = 1, z1.im = 2

Complex z2(1); // z2.re = 1, z2.im = 0

Complex z3; // z3.re = 0, z3.im = 0

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

Complex z4 = 13; // z4.re = 13, z4.im = 0

Здесь сначала создается безымянное комплексное число Complex(13) с использованием конструктора, которое затем используется для инициализации переменной z4.

Реализацию функций для работы с комплексными числами разместим в файле UnComplex.cpp.

// Файл UnComplex.cpp

#include "UnComplex.h"

#include <iostream.h>

// Функции-члены класса Complex

double Complex::Arg() // Аргумент комплексного числа

{ return atan2(im, re); }

Функция математической библиотеки (заголовочный файл math.h)

double atan2(double y, double x);

возвращает значение arctg(y/x). Она работает корректно, даже когда угол близок к π/2 или -π/2 (x близко к 0).

double Complex :: Abs() // Модуль комплексного числа

{ return sqrt(re * re + im * im); }

Complex Complex :: operator*(Complex z) // Умножение двух комплексных

{

Complex t(re * z.re - im * z.im, re * z.im + im * z.re);

return t;

}

Так как функция умножения является членом класса, ей доступно комплексное число, для которого она вызывается. Это число, представленное re и im, рассматривается как первый сомножитель. Второй сомножитель z передается в функцию как аргумент.

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

Complex Complex :: operator*(double a) // Умножение на double

{

return *this * Complex(a);

}

В функции деления реализованы обычные формулы деления комплексных чисел:

Complex Complex :: operator/(Complex z) // Деление

{

double r = (re * z.re +im * z.im) / (z.re * z.re + z.im * z.im);

double i = (-re * z.im + im * z.re) / (z.re * z.re + z.im * z.im);

return Complex(r, i);

}

Функция получения противоположного по знаку комплексного числа реализована как функция-член без аргументов:

Complex Complex :: operator-() // Унарный минус,

{ // получение комплексного числа

return Complex(-re, -im); // с противоположным знаком

}

Напомним, что комплексное число можно представить в алгебраической, показательной или тригонометрической форме:

Программа 53. Комплексные числа - student2.ru .

Здесь x – действительная часть, y – мнимая часть, ρ – модуль комплексного числа, φ – аргумент. Корень степени m находится по формуле:

Программа 53. Комплексные числа - student2.ru

Функция Roots находит все корни m-й степени из комплексного числа и заносит их в массив rts

void Complex::Roots(int m, Complex rts[]) // Извлечение корней

{ // степени m

double angle = Arg(); // Аргумент

double mod = Abs(); // Модуль

mod = pow(mod, 1.0 / m); // Корень m-й степени из модуля

for(int k = 0; k < m; k++) // Получение m корней

rts[k] = Polar(mod, (angle + 2 * k * M_PI) / m);

}

void Complex::Print() // Функция вывода комплексного числа

{ cout << "(" << re << ", " << im << ")"; }

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

Complex operator+(Complex z, Complex t) // Сложение

{ return z += t; }

Для реализации сложения двух комплексных использован перегруженный оператор +=, аналогично, для реализации вычитания используется оператор -=.

Complex operator-(Complex z, Complex t) // Вычитание

{ return z -= t; }

//Умножение вещественного на комплексное

Complex operator*(double a, Complex z)

{

return z * a; // Умножение комплексного на double

}

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

Следующая функция обеспечивает получение комплексного числа по его модулю и аргументу:

Complex Polar(double mod, double arg)

{ return Complex(mod * cos(arg), mod * sin(arg)); }

Целую степень комплексного числа можно найти по формуле:

Программа 53. Комплексные числа - student2.ru .

Функция Pow реализует эту формулу.

Complex Pow(Complex z, int m) // Возведение комплексного числа

{ // в степень m

double angle = z.Arg(); // Аргумент

double mod = z.Abs(); // Модуль

angle *= m; // Увеличение аргумента в m раз

double mp = 1.0; // m-я степень модуля

for(int k = 0; k < m; k++) // находится с помощью

mp *= mod; // произведения

return Polar(mp, angle);

}

В качестве примера использования класса комплексных чисел решим приведенное кубическое уравнение:

Программа 53. Комплексные числа - student2.ru .

Его корни можно выразить формулой Кардано:

Программа 53. Комплексные числа - student2.ru .

Решение уравнения дают такие комбинации кубических корней, произведение которых равно –p/3.

Функцию main поместим в файле UnMainComplex.cpp.

#include ”UnComplex.h”

#include <iostream.h>

#include <conio.h>

#include "Rus.h"

int main()

{

const double eps = 0.1E-4; // Малое число (точность)

double x, y;

cout << Rus("Решаем приведенное кубическое уравнение \n”

” z^3 + p*z + q = 0\n");

cout << Rus("Введите действительную и мнимую части p: ");

cin >> x >> y;

Complex p(x, y); // Создание коэффициента p

cout << Rus("Введите действительную и мнимую части q: ");

cin >> x >> y;

Complex q(x, y); // Создание коэффициента q

Complex inner[2]; // Массив для квадратных корней

// Массивы для первого и второго кубического корня

Complex root3_1[3], root3_2[3];

Complex D; // Дискриминант кубического уравнения

D = q * q / 4 + p * p * p / 27;

D.Roots(2, inner); // Квадратный корень из дискриминанта

// Первое выражение под куб. корнем

Complex D1 = (-0.5) * q + inner[0];

// Второе выражение под куб. корнем

Complex D2 = (-0.5) * q - inner[0];

D1.Roots(3, root3_1); // Извлечение первого кубического корня

D2.Roots(3, root3_2); // Извлечение второго кубического корня

Complex p3 = -p / 3; // Критерий для отбора корней

Complex eq; // Левая часть уравнения

Complex z; // Переменная для корня

Complex prod; // Произведение кубических корней

// Перебор возможных комбинаций кубических корней

for(int i = 0; i < 3; i++) // Перебор значений первого кубич. корня

for(int j = 0; j < 3; j++){ // Перебор значений второго кубич. корня

prod = root3_1[i] * root3_2[j]; //Произведение кубических корней

double err = (prod - p3).Abs(); //Отклонение произведения от -p/3

if( err < eps){ //Если отклонение мало,

z = root3_1[i] + root3_2[j]; //это корень

cout << Rus("\nКорень z = "); z.Print();

eq = Pow(z, 3) + p * z + q; //Подстановка корня в уравнение

cout << Rus("\nПроверка: z^3 + p*z + q = "); eq.Print();

}

}

getch();

return 0;

}

В качестве примера решим уравнение

Программа 53. Комплексные числа - student2.ru ,

имеющее корни:

Программа 53. Комплексные числа - student2.ru .

Далее приводится диалог с программой.

Решаем приведенное кубическое уравнение

z^3 + p*z + q = 0

Введите действительную и мнимую части p: -2 0

Введите действительную и мнимую части q: 1 0

Корень z = (1, 0)

Проверка: z^3 + p*z + q = (0, 0)

Корень z = (-1.61803, 1.94289e-16)

Проверка: z^3 + p*z + q = (0, 1.13739e-15)

Корень z = (0.618034, 0)

Проверка: z^3 + p*z + q = (0, 0)

Наши рекомендации