Метод Ньютона для комплексных чисел [закрыт]

120
12 августа 2019, 03:10

Здраствуйте, должен решить уравнение z^3 - 1 = 0, z - комплексное число.

  1. Код работает, только вывод один корень из трех, но верный. Что нудно сделать, чтобы выводило три корня? Как мне кажется, проблема в том, что нигде не задается (не передается) стартовая точка и по этому один корень, а так бы для разных точек были бы разные корни, но я в этом не уверен.
  2. На основе результатов нужно будет сделать график бассейнов решений, т.е от это будет комплексная плоскость, на которой каждый пиксель будет приводить одному из решений. Как это сделать, может кто-то знает? Как мне кажется, это должно быть два цикла с очень маленьким шагом, но что дальше?

Код :

#include <cmath>
#include <iostream>
using namespace std;
class CComplex
{
public :
    double _re;
    double _im;
    CComplex();
    CComplex(double re, double im);
    CComplex(const CComplex &pCopy);
    CComplex conjugate();
    double complexfabs();
    CComplex operator + (CComplex pAdd);
    CComplex operator - (CComplex pAdd);
    CComplex operator * (CComplex pMul);
    CComplex operator / (CComplex pDiv);
    CComplex uintpower(unsigned int n);
    friend ostream& operator << (ostream &out, const CComplex pVal)
    {
        out<<pVal._re<<(pVal._im < 0 ? " - " : " + ")<<fabs(pVal._im)<<"i";
        return out;
    }
};
CComplex::CComplex()
{
    _re = _im = 0;
}
CComplex::CComplex(double re, double im)
{
    _re = re;
    _im = im;
}
CComplex::CComplex(const CComplex &pCopy)
{
    _re = pCopy._re;
    _im = pCopy._im;
}
CComplex
CComplex::conjugate()
{
    CComplex pThis = (*this);
    pThis._im *= -1;
    return pThis;
}
double CComplex::complexfabs()
{
    return _re*_re + _im*_im;
}
CComplex
CComplex::operator +(CComplex pAdd)
{
    CComplex pThis = (*this);
    pThis._re += pAdd._re;
    pThis._im += pAdd._im;
    return pThis;
}
CComplex
CComplex::operator - (CComplex pAdd)
{
    CComplex pThis = (*this);
    pThis._re -= pAdd._re;
    pThis._im -= pAdd._im;
    return pThis;
}
CComplex
CComplex::operator *(CComplex pMul)
{
    CComplex pThis = (*this);
    pThis._re = _re*pMul._re - _im*pMul._im;
    pThis._im = _re*pMul._im + _im*pMul._re;
    return pThis;
}
CComplex
CComplex::operator / (CComplex pDiv)
{
    CComplex pThis = (*this);
    double divider = pDiv.complexfabs();
    pThis = pThis*pDiv.conjugate();
    pThis._re /= divider;
    pThis._im /= divider;
    return pThis;
}
CComplex
CComplex::uintpower(unsigned int n)
{
    CComplex pThis = CComplex(1, 0);
    for(unsigned int i = 0; i < n; i++)
        pThis = pThis*(*this);
    return pThis;
}
CComplex f(CComplex z, unsigned int n)
{
    return z.uintpower(n) - CComplex(1, 0);
}
CComplex df(CComplex z, unsigned int n)
{
    return CComplex(n, 0)*z.uintpower(n - 1);
}
int main()
{
    unsigned int n = 3;
    unsigned int i;
    double err = 1e-12;
    CComplex z(1,1);

    std::cout << "First root" <<std::endl;
    for(i = 0; f(z, n).complexfabs() > err; i++)
    {
        z = z - f(z, n) / df(z, n);
        cout<<"\riteration "<<i + 1<<" root : "<<z<<std::endl;    
    }
   system("pause");
    return 0;
}
Answer 1

Кубический корень имеет три ответа, между каждыми ответами разница 2π/3 в угловом смысле. Вам нужно перевести первый ответ в экспонентный формат x+iy=r*exp(iw). Другие ответы будут r*exp(i(w-2π/3)) и r*exp(i(w+2π/3)). Дальше эти ответы перевести назад.

r:=sqrt(x*x+y*y)
w:=atan2(y,x)
w2:=w-2π/3 
w3:=w+2π/3 
x2:=r*cos(w2)
y2:=r*sin(w2)
x3:=r*cos(w3)
y3:=r*sin(w3)

Пример вывода трёх решений:

    for(i = 0; f(z, n).complexfabs() > err; i++)
    {
        z = z - f(z, n) / df(z, n);
        cout<<"\riteration "<<i + 1<<" root : "<<z<<std::endl;   
                double r = sqrt(z._re*z._re+z._im*z._im);
                double w = atan2(z._im,z._re);
                double const PI = 3.1416;
                CComplex z2(r*cos(w-2.0*PI/3.0),r*sin(w-2.0*PI/3.0));
                cout<<"\riteration "<<i + 1<<" root : "<<z2<<std::endl;
                CComplex z3(r*cos(w+2.0*PI/3.0),r*sin(w+2.0*PI/3.0));
                cout<<"\riteration "<<i + 1<<" root : "<<z3<<std::endl;        
} //for

Ответом может быть при начальной точке (-1,1) такой:

iteration 1 root : -0.666667 + 0.833333i
iteration 1 root : 1.05502 + 0.160678i
iteration 1 root : -0.38835 - 0.994019i
iteration 2 root : -0.508692 + 0.8411i
iteration 2 root : 0.98276 + 0.0199854i
iteration 2 root : -0.474064 - 0.861092i
iteration 3 root : -0.49933 + 0.866269i
iteration 3 root : 0.999876 - 0.000707022i
iteration 3 root : -0.500542 - 0.865569i
iteration 4 root : -0.5 + 0.866025i
iteration 4 root : 1 - 4.72405e-06i
iteration 4 root : -0.499995 - 0.866028i
iteration 5 root : -0.5 + 0.866025i
iteration 5 root : 1 - 4.89761e-06i
iteration 5 root : -0.499996 - 0.866028i

Главный ответ -0.5 + 0.866025i отличается от основного ответа, но ответ красивый можно получить из второго решения.

READ ALSO
Обмен местами строк матрицы

Обмен местами строк матрицы

Необходимо поменять местами две строки матрицыНашел в интернете несколько примеров в которых используется поэлементный обмен

109
CryptoAPI генерация RSA ключей

CryptoAPI генерация RSA ключей

Необходимо генерировать закрытый и открытый ключ

116
Конвертировать черно-белое изображение малого размера в матрицу того же размера на C++

Конвертировать черно-белое изображение малого размера в матрицу того же размера на C++

Допустим есть черно-белое изображение размера 10x10 пикселей, то его нужно перевести в матрицу 10x10 в которой черному цвету будет соответствовать...

101
Вывести все минимальные числа

Вывести все минимальные числа

Есть такое задание: в массиве найти минимальное числоЕсли минимальных чисел несколько, то присвоить им среднее арифметическое исходного...

105