Дмитрий
Дмитрий07 вересня 2022 р. 14:40

Інженерне рішення кубічного рівняння за допомогою тригонометричної формули Вієта

Як відомо, рішення кубічного рівняння було відоме ще з 16 століття. Однак навіть у наші дні інженери можуть зіткнутися з проблемою при його вирішенні. Ця складність обумовлена необхідністю вилучення кореня з комплексних чисел. Найбільш зручним рішенням є тригонометрична формула Вієта , яка значно менш відома в порівнянні з формулою Кардано. Для привернення уваги до теми я написав маленьку бібліотеку на C++ .


Реалізація

Бібліотека містить 3 сімейства класів: поліноміальне рівняння, коріння поліноміального рівняння та корінь поліноміального рівняння. Класи наведених рівнянь 1-го, 2-го і 3-го ступенів LinerNormalEquation, QuadraticNormalEquation і CubicNormalEquation успадковані від загального інтерфейсу AbstractPolynomialEquation. У цьому прикладі я обмежився розповсюдженням лише наведених рівнянь. Їхні основні методи roots() — повертає покажчик на клас, що зберігає рішення рівняння, root(int n) — повертає n корінь рівняння і value(…) — повертає значення рівняння при підстановці в нього заданого аргументу. Функція decomposed() повертає розкладання поточного полінома на множники. Основна теорема алгебри стверджує, що будь-який многочлен можна розкласти на множники ступеня, що не перевищує 2. Тому рівняння третього ступеня може бути розкладене або на 3 множника першого ступеня, або на 1 першого і 1 другого ступеня.

Інтерфейс

class AbstractPolynomialEquation
{
public:
    virtual ~AbstractPolynomialEquation() { deleteRoots(); }
    virtual int equationType() const = 0;
    virtual std::list<double> coefficients() const = 0;
    virtual double value( const double &x ) const = 0;
    virtual std::complex<double> value( const std::complex<double> &x ) const = 0;
    virtual std::complex<double> value( const std::unique_ptr<AbstractPolynomialRoot> &x ) {
        if(x->isReal())
            return std::complex<double>( value( x->real() ) );
        return value( x->toComplex() );
    }
    virtual const AbstractPolynomialEquationRoots *roots() const = 0;
    const std::unique_ptr<AbstractPolynomialRoot> root(int number) const { return roots()->root(number); }
    virtual std::list<std::unique_ptr<AbstractPolynomialEquation>> decomposed() const = 0;
    virtual bool isNormal() const = 0;

    friend std::ostream &operator<< (std::ostream &out, const AbstractPolynomialEquation &equation) {
        out << equation.toString() + " = 0.";
        return out;
    }
protected:
    virtual std::string toString() const = 0;
    mutable AbstractPolynomialEquationRoots *myroots = nullptr;
    void deleteRoots() const {
        if(myroots) {
            delete myroots;
            myroots = nullptr;
        }
    }
};

Лінійне рівняння

class LinerNormalEquation : public AbstractPolynomialEquation
{
public:
    explicit LinerNormalEquation(const double &coef0);
    void setCoef0(const double &coef0);

    LinerNormalEquation operator+( const double &val );
    LinerNormalEquation operator-( const double &val );
    LinerNormalEquation operator+( const LinerNormalEquation &eq );
    double operator-( const LinerNormalEquation &eq ) const;

    virtual int equationType() const override {return LINER;}
    virtual std::list<double> coefficients() const override { std::list<double> list; list.push_back( my0 ); list.push_back( 1 ); return list; }
    virtual double value( const double &x ) const override { return x + my0; }
    virtual std::complex<double> value( const std::complex<double> &x ) const override { return x + my0; }
    virtual const AbstractPolynomialEquationRoots *roots() const override;
    virtual std::list<std::unique_ptr<AbstractPolynomialEquation>> decomposed() const override;
    virtual bool isNormal() const override {return true;}
protected:
    virtual std::string toString() const override;
private:
    double my0;
};

Реалізація

LinerNormalEquation::LinerNormalEquation(const double &coef0)
{
    my0 = coef0;
}

void PolynomialEquation::LinerNormalEquation::setCoef0(const double &coef0)
{
    my0 = coef0;
    deleteRoots();
}

LinerNormalEquation LinerNormalEquation::operator+(const double &val)
{
    return LinerNormalEquation( this->my0 + val );
}

LinerNormalEquation LinerNormalEquation::operator-(const double &val)
{
    return LinerNormalEquation( this->my0 - val );
}

LinerNormalEquation LinerNormalEquation::operator+(const LinerNormalEquation &eq)
{
    return LinerNormalEquation( (this->my0 + eq.my0)/2 );
}

double LinerNormalEquation::operator-(const LinerNormalEquation &eq) const
{
    return this->my0 - eq.my0;
}

const AbstractPolynomialEquationRoots *PolynomialEquation::LinerNormalEquation::roots() const
{
    if(!myroots)
        myroots = new LinerEquationRoot( -my0 );
    return myroots;
}

std::list<std::unique_ptr<AbstractPolynomialEquation> > LinerNormalEquation::decomposed() const
{
    std::list<std::unique_ptr<AbstractPolynomialEquation> > root;
    root.push_back( std::make_unique<LinerNormalEquation>( this->my0 ) );
    return root;
}

std::string LinerNormalEquation::toString() const
{
    return std::string("x") + ( my0 > 0 ? std::string("+") : std::string() ) + ( my0 == 0 ? std::string() : std::to_string( my0 ) );
}

Квадратне рівняння

class QuadraticNormalEquation : public AbstractPolynomialEquation
{
public:
    QuadraticNormalEquation( double coef1, double coef0);
    virtual ~QuadraticNormalEquation() {}
    void setCoef0(const double &coef0);
    void setCoef1(const double &coef1);

    QuadraticNormalEquation operator+( const double &val );
    QuadraticNormalEquation operator-( const double &val );
    QuadraticNormalEquation operator+( const QuadraticNormalEquation &eq );
    QuadraticNormalEquation operator+( const LinerNormalEquation &eq );
    QuadraticNormalEquation operator-( const LinerNormalEquation &eq );

    double discriminant() const;
    virtual int equationType() const override { return QUADRATIC; }
    virtual std::list<double> coefficients() const override { std::list<double> list; list.push_back( my0 ); list.push_back( my1 ); list.push_back( 1 ); return list; }
    virtual double value( const double &x ) const override { return (x + my1)*x + my0; }
    virtual std::complex<double> value( const std::complex<double> &x ) const override { return (x + my1)*x + my0; }
    virtual const AbstractPolynomialEquationRoots *roots() const override;
    virtual std::list< std::unique_ptr<AbstractPolynomialEquation> > decomposed() const override;
    virtual bool isNormal() const override {return true;}
protected:
    virtual std::string toString() const override;
private:
    double my0;
    double my1;
};

Реалізація

QuadraticNormalEquation::QuadraticNormalEquation( double coef1, double coef0)
    : my0(coef0), my1(coef1)
{
}

void QuadraticNormalEquation::setCoef0(const double &coef0)
{
    my0 = coef0;
    deleteRoots();
}

void QuadraticNormalEquation::setCoef1(const double &coef1)
{
    my1 = coef1;
    deleteRoots();
}

QuadraticNormalEquation QuadraticNormalEquation::operator+( const double &val )
{
    return QuadraticNormalEquation( this->my1, this->my0 + val );
}

QuadraticNormalEquation QuadraticNormalEquation::operator-( const double &val )
{
    return QuadraticNormalEquation( this->my1, this->my0 - val );
}

QuadraticNormalEquation QuadraticNormalEquation::operator+(const QuadraticNormalEquation &eq)
{
    return QuadraticNormalEquation( (this->my1+eq.my1)/2, (this->my0+eq.my0)/2 );
}

QuadraticNormalEquation QuadraticNormalEquation::operator-(const LinerNormalEquation &eq)
{
    return QuadraticNormalEquation( this->my1 - 1, this->my0 - eq.coefficients().front() );
}

QuadraticNormalEquation QuadraticNormalEquation::operator+(const LinerNormalEquation &eq)
{
    return QuadraticNormalEquation( this->my1 + 1, this->my0 + eq.coefficients().front() );
}

double QuadraticNormalEquation::discriminant() const
{
    return my1*my1 - 4*my0;
}

const AbstractPolynomialEquationRoots *QuadraticNormalEquation::roots() const
{
    if(!myroots) {
        auto d = discriminant();
        myroots = new QuadraticImageEquationRoots( -my1/2, sqrt(-d)/2 );
    }
    return myroots;
}

std::list<std::unique_ptr<AbstractPolynomialEquation> > QuadraticNormalEquation::decomposed() const
{
    std::list<std::unique_ptr<AbstractPolynomialEquation> > eqs;
    if( this->roots()->rootsType() == QUADRAT_REAL ) {
        eqs.push_back( std::make_unique<LinerNormalEquation>( -this->roots()->root( 1 )->real() ) );
        eqs.push_back( std::make_unique<LinerNormalEquation>( -this->roots()->root( 2 )->real() ) );
    }
    else if( this->roots()->rootsType() == QUADRAT_IMAGE ) {
        eqs.push_back( std::make_unique<QuadraticNormalEquation>( *this ) );
    }
    return eqs;
}

std::string QuadraticNormalEquation::toString() const
{
    return std::string("x^2")
            + ( my1 > 0 ? std::string("+") : std::string("") ) + ( my1==0 ? std::string("") : std::to_string( my1 ) + std::string("*x") )
            + ( my0 > 0 ? std::string("+") : std::string("") ) + ( my0==0 ? std::string("") : std::to_string( my0 ) );
}

Кубічне рівняння

class CubicNormalEquation : public AbstractPolynomialEquation
{
public:
    CubicNormalEquation(double coef2, double coef1, double coef0);
    void setCoef0(const double &coef0);
    void setCoef1(const double &coef1);
    void setCoef2(const double &coef2);

    CubicNormalEquation operator+( const CubicNormalEquation &eq );
    CubicNormalEquation operator+( const LinerNormalEquation &eq );
    CubicNormalEquation operator-( const LinerNormalEquation &eq );
    CubicNormalEquation operator+( const QuadraticNormalEquation &eq );
    CubicNormalEquation operator-( const QuadraticNormalEquation &eq );

    double discriminant() const;
    double qu() const;
    double re() const;
    double fi() const;
    virtual int equationType() const override {return CUBIC;}
    virtual std::list<double> coefficients() const override { std::list<double> list; list.push_back( my0 ); list.push_back( my1 ); list.push_back( my2 ); list.push_back( 1 ); return list; }
    virtual double value( const double &x ) const override { return ( (x + my2)*x + my1 ) * x + my0; }
    virtual std::complex<double> value( const std::complex<double> &x ) const override { return ( (x + my2)*x + my1 ) * x + my0; }
    virtual const AbstractPolynomialEquationRoots *roots() const override;
    virtual std::list<std::unique_ptr<AbstractPolynomialEquation>> decomposed() const override;
    virtual bool isNormal() const override {return true;}
protected:
    virtual std::string toString() const override;
private:
    double my0;
    double my1;
    double my2;
};

Реалізація

CubicNormalEquation::CubicNormalEquation( double coef2, double coef1, double coef0 )
    : my0(coef0), my1(coef1), my2(coef2)
{
}

void CubicNormalEquation::setCoef0(const double &coef0)
{
    my0 = coef0;
    deleteRoots();
}

void CubicNormalEquation::setCoef1(const double &coef1)
{
    my1 = coef1;
    deleteRoots();
}

void CubicNormalEquation::setCoef2(const double &coef2)
{
    my2 = coef2;
    deleteRoots();
}

CubicNormalEquation CubicNormalEquation::operator+(const CubicNormalEquation &eq)
{
    return CubicNormalEquation( (this->my2+eq.my2)/2, (this->my1+eq.my1)/2, (this->my0+eq.my0)/2 );
}

CubicNormalEquation CubicNormalEquation::operator+( const LinerNormalEquation &eq )
{
    auto coef = eq.coefficients();
    return CubicNormalEquation( this->my2, this->my1 + 1, this->my0 + coef.front() );
}

CubicNormalEquation CubicNormalEquation::operator-( const LinerNormalEquation &eq )
{
    auto coef = eq.coefficients();
    return CubicNormalEquation( this->my2, this->my1 - 1, this->my0 - coef.front() );
}

CubicNormalEquation CubicNormalEquation::operator+( const QuadraticNormalEquation &eq )
{
    auto coef = eq.coefficients();
    return CubicNormalEquation( this->my2 + 1, this->my1 + *next( coef.begin() ), this->my0 + coef.front() );
}

CubicNormalEquation CubicNormalEquation::operator-( const QuadraticNormalEquation &eq )
{
    auto coef = eq.coefficients();
    return CubicNormalEquation( this->my2 - 1, this->my1 - *next( coef.begin() ), this->my0 - coef.front() );
}

double CubicNormalEquation::discriminant() const //
{
    auto q = qu();
    auto r = re();
    return q*q*q - r*r;
}

double CubicNormalEquation::qu() const
{
    return (my2*my2 - my1*3) / 9;
}

double CubicNormalEquation::re() const
{
    return (my2 * (my2*my2*2 - my1*9) + 27*my0) / 54;
}

double CubicNormalEquation::fi() const
{
    auto q = qu();
    auto q_cub = q*q*q;
    auto r = re();
    auto s = q*q*q - r*r;
    if( s > 0 )
        return acos( r/sqrt(q_cub) ) / 3;
    else {
        if( q > 0 ) {
            return acosh( fabs( r )/sqrt( q_cub ) ) / 3;
        } else {
            return asinh( fabs( r )/sqrt( -q_cub ) ) / 3;
        }
    }
}

const AbstractPolynomialEquationRoots *CubicNormalEquation::roots() const
{
    if(!myroots) {
        auto r = re();
        auto q = qu();
        auto a_3 = my2 / 3;
        auto s = q*q*q - r*r;
        if(r==0 && q==0) {
            auto x1 = - a_3;
            myroots = new CubicRealEquationRoots( x1, x1, x1 );
            return myroots;
        }
        if( s == 0 ) {
            auto x1 = -2 * cbrt(r) - a_3;
            auto x23 = cbrt(r) - a_3;
            myroots = new CubicRealEquationRoots( x1, x23, x23 );
            return myroots;
        }

        auto f = fi();
        if( s > 0 ) {
            auto q_sqrt = sqrt( q );
            auto x1 = - 2 * q_sqrt * cos( f ) - a_3;
            auto x2 = - 2 * q_sqrt * cos( f + 2.0 * M_PI / 3 ) - a_3;
            auto x3 = - 2 * q_sqrt * cos( f - 2.0 * M_PI / 3 ) - a_3;
            myroots = new CubicRealEquationRoots( x1, x2, x3 );
        } else {
            if( q == 0) {
                auto x = - cbrt( my0 - a_3*a_3*a_3 ) - a_3;
                auto re = -( my2 + x )/2;
                auto im = sqrt( fabs( (my2 - 3*x)*(my2 + x) - 4*my1 ) )/2;
                myroots = new CubicImageEquationRoots( x, re, im );
                return myroots;
            }
            if( q > 0 ) {
                auto q_sqrt = sqrt( q );
                auto x = - q_sqrt * 2.0 * sgn(r) * cosh( f ) - a_3;
                auto re = q_sqrt * sgn(r) * cosh( f ) - a_3;
                auto im = SQRT_3 * q_sqrt * sinh( f );
                myroots = new CubicImageEquationRoots( x, re, im );
            } else {
                auto q_sqrt = sqrt( -q );
                auto x = - q_sqrt * 2.0 * sgn(r) * sinh( f ) - a_3;
                auto re = q_sqrt * sgn(r) * sinh( f ) - a_3;
                auto im = SQRT_3 * q_sqrt * cosh( f );
                myroots = new CubicImageEquationRoots( x, re, im );
            }
        }
    }
    return myroots;
}

std::list<std::unique_ptr<AbstractPolynomialEquation> > CubicNormalEquation::decomposed() const
{
    std::list<std::unique_ptr<AbstractPolynomialEquation> > eqs;
    eqs.push_back( std::make_unique<LinerNormalEquation>( -this->roots()->root( 1 )->real() ) );
    if( roots()->rootsType() == CUB_REAL ) {
        eqs.push_back( std::make_unique<LinerNormalEquation>( -this->roots()->root( 2 )->real() ) );
        eqs.push_back( std::make_unique<LinerNormalEquation>( -this->roots()->root( 3 )->real() ) );
    }
    else if( roots()->rootsType() == CUB_IMAGE ) {
        eqs.push_back( std::make_unique<QuadraticNormalEquation>( -2.0*this->roots()->root( 2 )->real(), fabs( this->roots()->root( 2 )->toComplex() ) ) );
    }
    return eqs;
}

std::string CubicNormalEquation::toString() const
{
    return std::string("x^3")
            + ( my2 > 0 ? std::string("+") : std::string() ) + ( my2==0 ? std::string() : ( std::to_string( my2 ) + std::string("*x^2") ) )
            + ( my1 > 0 ? std::string("+") : std::string() ) + ( my1==0 ? std::string() : ( std::to_string( my1 ) + std::string("*x") ) )
            + ( my0 > 0 ? std::string("+") : std::string() ) + ( my0==0 ? std::string() : std::to_string( my0 ) );
}

Класи зберігачі рішень рівнянь LinerEquationRoot, QuadraticRealEquationRoots, QuadraticImageEquationRoots. CubicRealEquationRoots, CubicImageEquationRoots успадковані від загального інтерфейсу AbstractPolynomialEquationRoots і класифікуються за двома ознаками. Перший – ступінь рівняння, другий – характеристика коренів рівняння. Лінійне рівняння є тривіальним випадком — має один дійсний корінь. Квадратне і кубічне рівняння може мати комплексне коріння. Таке коріння завжди існує парами x 1 = R + i M і x 2 = R – i M. Тому зберігаються вони як дійсна та уявна частини. Справжнє коріння зберігається як безпосередньо свої значення.

Інтерфейс

class AbstractPolynomialEquationRoots
{
public:
    virtual ~AbstractPolynomialEquationRoots() { /*std::cout << "delete AbstractPolynomialEquationRoots";*/ }
    virtual int rootsType() const = 0;
    virtual std::unique_ptr<AbstractPolynomialRoot> root(int number) const = 0;

    friend std::ostream &operator<< (std::ostream &out, const AbstractPolynomialEquationRoots *root) {
        out << root->toString();
        return out;
    }
protected:
    virtual std::string toString() const = 0;
};

Коріння лінійного рівняння

class LinerEquationRoot : public AbstractPolynomialEquationRoots
{
public:
    explicit LinerEquationRoot(const double &root);
    virtual ~LinerEquationRoot() {}
    virtual int rootsType() const override {return LINE;}
    virtual std::unique_ptr<AbstractPolynomialRoot> root(int number) const override {
        return number == 1 ? std::make_unique<RealPolynomialRoot>(myx1) : nullptr;
    }
protected:
    virtual std::string toString() const override;

private:
    double myx1;
};

Реалізація

LinerEquationRoot::LinerEquationRoot(const double &root)
    : myx1(root)
{
}

std::string LinerEquationRoot::toString() const
{
    return "x = " + std::to_string(myx1) + ".";
}

Коріння квадратного рівняння

class QuadraticRealEquationRoots : public AbstractPolynomialEquationRoots
{
public:
    QuadraticRealEquationRoots(const double &root1, const double &root2);
    virtual ~QuadraticRealEquationRoots() {}
    virtual int rootsType() const override {return QUADRAT_REAL;}
    virtual std::unique_ptr<AbstractPolynomialRoot> root(int number) const override;

protected:
    virtual std::string toString() const override;
private:
    double myx1;
    double myx2;
};

class QuadraticImageEquationRoots : public AbstractPolynomialEquationRoots
{
public:
    QuadraticImageEquationRoots( double real,  double image);
    virtual ~QuadraticImageEquationRoots() {}
    virtual int rootsType() const override {return QUADRAT_IMAGE;}
    virtual std::unique_ptr<AbstractPolynomialRoot> root(int number) const override;

protected:
    virtual std::string toString() const override;
private:
    double myre;
    double myim;
};

Реалізація

QuadraticRealEquationRoots::QuadraticRealEquationRoots(const double &root1, const double &root2)
    : myx1( root1 ), myx2( root2 )
{
}

std::unique_ptr<AbstractPolynomialRoot> QuadraticRealEquationRoots::root(int number) const
{
    switch (number) {
    case 1:
        return std::make_unique<RealPolynomialRoot>(myx1);
    case 2:
        return std::make_unique<RealPolynomialRoot>(myx2);
    default:
        return nullptr;
    }
}

std::string QuadraticRealEquationRoots::toString() const
{
    return "x1 = " + std::to_string( myx1 ) + "; x2 = " + std::to_string( myx2 ) + ".";
}

QuadraticImageEquationRoots::QuadraticImageEquationRoots(double real, double image)
    : myre( real ), myim( image )
{
}

std::unique_ptr<AbstractPolynomialRoot> QuadraticImageEquationRoots::root(int number) const
{
    switch (number) {
    case 1:
        return std::make_unique<ImagePolynomialRoot>(myre, myim);
    case 2:
        return std::make_unique<ImagePolynomialRoot>(myre, -myim);
    default:
        return nullptr;
    }
}

std::string QuadraticImageEquationRoots::toString() const
{
    return "x1 = " + std::to_string( myre ) + " + j" + std::to_string( myim )
            + "; x2 = " + std::to_string( myre ) + " - j" + std::to_string( myim ) + ".";
}

Коріння кубічного рівняння

class CubicRealEquationRoots : public AbstractPolynomialEquationRoots
{
public:
    CubicRealEquationRoots(const double &root1, const double &root2, const double &root3);
    virtual ~CubicRealEquationRoots() {}
    virtual int rootsType() const override {return CUB_REAL;}
    virtual std::unique_ptr<AbstractPolynomialRoot> root(int number) const override;

protected:
    virtual std::string toString() const override;
private:
    double myx1;
    double myx2;
    double myx3;
};

class CubicImageEquationRoots : public AbstractPolynomialEquationRoots
{
public:
    CubicImageEquationRoots(const double &root, const double &real, const double &image);
    virtual ~CubicImageEquationRoots() {}
    virtual int rootsType() const override {return CUB_IMAGE;}
    virtual std::unique_ptr<AbstractPolynomialRoot> root(int number) const override;

protected:
    virtual std::string toString() const override;
private:
    double myx1;
    double myre;
    double myim;
};

Реалізація

CubicRealEquationRoots::CubicRealEquationRoots(const double &root1, const double &root2, const double &root3)
    : myx1( root1 ), myx2( root2 ), myx3( root3 )
{
}

std::unique_ptr<AbstractPolynomialRoot> CubicRealEquationRoots::root(int number) const
{
    switch (number) {
    case 1:
        return std::make_unique<RealPolynomialRoot>(myx1);
    case 2:
        return std::make_unique<RealPolynomialRoot>(myx2);
    case 3:
        return std::make_unique<RealPolynomialRoot>(myx3);
    default:
        return nullptr;
    }
}

std::string CubicRealEquationRoots::toString() const
{
    return "x1 = " + std::to_string( myx1 )
            + "; x2 = " + std::to_string( myx2 )
            + "; x3 = " + std::to_string( myx3 );
}

CubicImageEquationRoots::CubicImageEquationRoots(const double &root, const double &real, const double &image)
    : myx1( root ), myre( real ), myim( image )
{
}

//-----------------------------------------------------------

std::unique_ptr<AbstractPolynomialRoot> CubicImageEquationRoots::root(int number) const
{
    switch (number) {
    case 1:
        return std::make_unique<RealPolynomialRoot>(myx1);
    case 2:
        return std::make_unique<ImagePolynomialRoot>(myre, myim);
    case 3:
        return std::make_unique<ImagePolynomialRoot>(myre, -myim);
    default:
        return nullptr;
    }
}

std::string CubicImageEquationRoots::toString() const
{
    return "x1 = " + std::to_string( myx1 )
            + "; x2 = " + (myre == 0 ? std::string() : std::to_string( myre ) + std::string(" + ")) + "j" + std::to_string( myim )
            + "; x3 = " + (myre == 0 ? std::string() : std::to_string( myre ) + std::string(" ")) + "- j" + std::to_string( myim )
            + ".";
}

Для доступу до величин коренів створені об'єкти RealPolynomialRoot та ImagePolynomialRoot, успадковані від AbstractPolynomialRoot. Корінь повертається як розумного покажчика unique_ptr . Цей прийом дозволяє перетворити покажчик на об'єкт з невизначеним часом життя на об'єкт, що видаляється при виході з області його видимості.

Інтерфейс

class AbstractPolynomialRoot
{
public:
    virtual std::complex<double> toComplex() const = 0;
    virtual double real() const = 0;
    virtual double image() const = 0;
    virtual bool isReal() const = 0;
};

Справжній корінь

class RealPolynomialRoot : public AbstractPolynomialRoot
{
public:
    explicit RealPolynomialRoot( const double &x )
        : myx(x) {}
    virtual std::complex<double> toComplex() const override { return std::complex<double>(myx, 0); }
    virtual double real() const override { return myx; }
    virtual double image() const override { return 0; }
    virtual bool isReal() const override { return true; }
private:
    double myx;
};

Уявний корінь

class ImagePolynomialRoot : public AbstractPolynomialRoot
{
public:
    ImagePolynomialRoot( const double &r, const double &i )
        : myr(r), myi(i) {}
    virtual std::complex<double> toComplex() const override { return std::complex<double>(myr, myi); }
    virtual double real() const override { return myr; }
    virtual double image() const override { return myi; }
    virtual bool isReal() const override { return false; }
private:
    double myr, myi;
};

Висновок

Незважаючи на простоту, формули розв'язання поліноміальних рівнянь є дуже складними виразами. Крім рішення рівняння третього ступеня відоме рішення Ferrari для рівнянь четвертого ступеня. За інших випадках доводиться використовувати чисельні методи. При цьому для пошуку комплексного коріння необхідні спеціальні методи. На ці теми планую написати такі статті.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 01:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 01:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 11:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 жовтня 2024 р. 14:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 08:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi24 червня 2024 р. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 06:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 03:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 09:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Слідкуйте за нами в соціальних мережах