Дмитрий7 сентября 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;
};

Заключение

Несмотря на кажущуюся простоту, формулы решения полиномиальных уравнений являются очень сложными выражениями. Кроме решения уравнения третьей степени известно решение Феррари для уравнений четвёртой степени. В остальных случаях приходится использовать численные методы. При этом для поиска комплексных корней необходимы специальные методы. На эти темы я планирую написать следующие статьи.

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

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг
YL

C++ - Тест 001. Первая программа и типы данных

  • Результат:66баллов,
  • Очки рейтинга-1
k
  • korsar
  • 23 ноября 2022 г. 9:57

C++ - Тест 005. Структуры и Классы

  • Результат:50баллов,
  • Очки рейтинга-4
TM

C++ - Тест 003. Условия и циклы

  • Результат:78баллов,
  • Очки рейтинга2
Последние комментарии
b

GameDev на Qt - Урок 5. Взрыв от пуль с помощью sprite картинки

Если вдруг кто-то прочитает.... Скачал проект, скомпилил, запустил. Всё красиво и объектно ориентировано, но вот FPS дико страдает, когда появляется 10+ врагов. Может есть какие-то надстрой…
  • juvf
  • 25 ноября 2022 г. 1:14

Qt/C++ - Урок 051. QMediaPlayer - Аудио плеер на Qt

Добрый день. Подскажите, как можно перехватить в Qt или Qml уровень воспроизводимого звука? Т.е. требуется сделать виртуальный винтажный индикатор (стрелочный или светодиодный), который бы …
  • juvf
  • 3 ноября 2022 г. 4:20

QML - Урок 007. ListView Qml. Динамическое создание и удаление элементов

Добрый день. Очень полезная статья. Спасибо. Вопрос такой: 1) нужно "взять" кнопку 2 пальцем (прикаснулись пальцем к кнопке 2, держим, через 2-3 кнопка оторвалась от ListView) и пере…

PyQt5 - Урок 007. Работаем с QML QtQuick (Сигналы и слоты)

А можно ли из QML сделать привязку свойства к свойству пайтоновского объекта? Ну, т.е. , например, у нашего объекта Calculator обхвялем свойства sumresult и subresult c с декоратором @pyqtProp…
МА

Распознавание изображений на Python с помощью TensorFlow и Keras

А что собственно выводит программа, как вывести то что она смогла распознать?
Сейчас обсуждают на форуме
АБ

Sorting the added QML elements in the ListModel

I am writing an alarm clock in QML, I am required to sort the alarms in ascending order (depending on the date or time (if there are several alarms on the same day). I've done the sorting …
АМ

Как добавить в скрипт размер каждого файла в Мб ?

IDLE (Python 3.10 64-bit) Win 10 Есть такой скрипт: Поиск перечня файлов в папке и запись списка: import ospath = 'E:\Мой Python\__Видеокурсы Python'rez = sorted(os.listdir(pa…
n
  • nkly
  • 18 октября 2022 г. 10:14

Как сохранить данные древовидной модели на основе QStandardItemModel в файл

Вы меня неправильно поняли. Допустим я собираю кулинарные рецепты и один из них - рецепт супа Харчо. Структура файла данных такова: { node:Рецепт супа Харчо parent:Вкусные блюда, …

Вопрос по Qt Creator

Добрый день. Не знаю, подобную проблему я не решал.

Задать другой класс div-у

Добрый день. Попробуйте использовать Selenium. Это библиотека есть в виде Python модуля и она позволяет загружать страницу и манипулировать html элементами. Как я понимаю, в ней можно…
О нас
Услуги
© EVILEG 2015-2022
Рекомендует хостинг TIMEWEB