Вначале немного теории. Как обычно, будем рассматривать уравнение в котором коэффициент при x3 равен нулю: x4 + px2 + qx + r = 0 (1) Представим это уравнение в виде произведения двух квадратных: x4 + px2 + qx + r = ( x2 + ax + b ) ( x2 - ax + c ) (2) Тогда для коэффициентов a, b, c получим следующую систему уравнений: b + c - a2 = p a ( c - b ) = q (3) bc = r Из первых двух уравнений системы (3) получаем: 2c = p + a2 + q/a (4) 2b = p + a2 - q/a Затем подставляем выражения для b и c в третье уравнение системы (3) и получаем уравнение шестой степени относительно a: a6 + 2pa4 + (p2 - 4r)a2 - q2 = 0 (5) Сделаем подстановку: y = a2. y3 + 2py2 + (p2 - 4r)y - q2 = 0 (6) Таким образом получается следующий метод решения уравнения четвёртой степени (1). Вначале решаем кубическое уравнение (6). Берём произвольный корень и получаем a. Затем подставляем a в (4) и находим b и c. Остаётся только решить два квадратных уравнения из (2) и получить четыре корня. Для нахождения действительных корней уравнения четвёртой степени предлагаю следующие две функции: typedef unsigned int nat; // x^4 + p * x^2 + q * x + r = 0 nat root4s ( double p, double q, double r, double * x ) { if ( r == 0 ) // это условие добавлено 21.10.2008 { *x = 0; return 1 + root3s ( p, q, x+1 ); } if ( q == 0 ) { m1: double t[2]; nat n = root2 ( p, r, t ); if ( n == 0 ) return 0; if ( t[0] >= 0 ) { x[0] = sqrt ( t[0] ); x[1] = - x[0]; n = 2; } else { n = 0; } if ( t[1] >= 0 ) { x[n] = sqrt ( t[1] ); x[n+1] = - x[n]; n += 2; } return n; } nat n = root3 ( p + p, p * p - 4. * r, -q * q, x ); double a = *x; if ( n == 3 ) { if ( a < x[1] ) a = x[1]; if ( a < x[2] ) a = x[2]; } if ( a <= 0 ) goto m1; // этот переход сделан 09.12.2011 p += a; a = sqrt ( a ); const double b = q / a; n = root2 ( a, 0.5 * ( p - b ), x ); n+= root2 ( -a, 0.5 * ( p + b ), x+n ); return n; } // x^4 + a * x^3 + b * x^2 + c * x + d = 0 nat root4 ( double a, double b, double c, double d, double * x ) { if ( a == 0 ) { return root4s ( b, c, d, x ); } if ( d == 0 ) { *x = 0; return 1 + root3 ( a, b, c, x+1 ); } const double e = a / 4; const double h = e * e; const double p = -6 * h + b; const double q = 8 * h * e - 2 * b * e + c; const double r = -3 * h * h + b * h - c * e + d; const nat n = root4s ( p, q, r, x ); for ( nat i = 0; i < n; ++i ) x[i] -= e; return n; }
Первая из них решает "неполное" уравнение, т.е. у которого коэффициент при x3 равен нулю,
а вторая сводит общий случай к предыдущему.
Следующие две функции, кроме вещественных корней, вычисляют также комплексные корни: void root4s ( double p, double q, double r, Complex & x1, Complex & x2, Complex & x3, Complex & x4 ); void root4 ( double a, double b, double c, double d, Complex & x1, Complex & x2, Complex & x3, Complex & x4 );Они устроены аналогично предыдущим функциям. Следующие две функции вычисляют корни уравнений с комплексными параметрами: void root4s ( const Complex & p, const Complex & q, const Complex & r, Complex & x1, Complex & x2, Complex & x3, Complex & x4 ); void root4 ( const Complex & a, const Complex & b, const Complex & c, const Complex & d, Complex & x1, Complex & x2, Complex & x3, Complex & x4 ) Исходники этих функций находятся в файле complex.cpp. Описание типа Complex смотрите в разделе Класс Complex. Наверх |