Алгебраические уравнения - Кубические уравнения

11 Nov in Math

Чаще всего кубические уравнения решают "тригонометрическим" методом, но там надо вычислять специальные функции, которые по сути являются подпрограммами, хотя и весьма оптимизированными. Можно поступить по другому - вначале найти один корень методом Ньютона, а затем, используя полученный корень, свести уравнение к квадратному для поиска остальных корней.


// x^3 + a * x + b = 0

static void cubic ( double a, double b, double & x )
{
double s = 1.;
while ( b + a > -1. )
{
a *= 4.;
b *= 8.;
s *= 0.5;
}
while ( b + a + a < -8. )
{
a *= 0.25;
b *= 0.125;
s *= 2.;
}
x = 1.5;
for ( int i = 9; --i >= 0; )
{
x -= ( x * ( x * x + a ) + b ) / ( 3. * x * x + a );
}
x *= s;
}

// x^3 + p * x + q = 0

int root3s ( double p, double q, double * x )
{
if ( q < 0 )
{
cubic ( p, q, *x );
}
else
if ( q > 0 )
{
cubic ( p, -q, *x );
*x = - *x;
}
else
{
*x = 0;
}
return 1 + root2 ( *x, p + (*x)*(*x), x+1 );
}

// x^3 + a * x^2 + b * x + c = 0

int root3 ( double a, double b, double c, double * x )
{
if ( c == 0 )
{
*x = 0;
}
else
{
const double a3 = a / 3.;
double p = b - 3.* a3 * a3;
double q = c - ( a3 * a3 + p ) * a3;
if ( q < 0 )
{
cubic ( p, q, *x );
}
else
if ( q > 0 )
{
cubic ( p, -q, *x );
*x = - *x;
}
else
{
*x = 0;
}
*x -= a3;
const double t = *x * ( *x * 3. + a * 2. ) + b;
if ( fabs ( t ) > 1e-3 )
{
*x -= ( *x * ( *x * ( *x + a ) + b ) + c ) / t;
}
a += *x;
b += *x * a;
}
return 1 + root2 ( a, b, x+1 );
}

Здесь рассматриваются два типа уравнений: общее (root3) и "неполное" (root3s). Обе функции возвращают количество найденных вещественных корней, а сами корни помещаются в массив по указателю x. Вначале отыскивается один корень ( а он всегда существует) методом Ньютона. Перед этим параметры уравнения путём масштабирования меняются таким образом, чтобы корень лежал между 1 и 2. В этом случае экспериментально (несколько миллионов испытаний) я установил, что достаточно 9 итераций. На самом деле нужно даже меньше, но на всякий случай пусть будет 9. После того как найден один корень кубическое уравнение сводится к квадратному.


В первоначальном варианте функции root3 уточнения корня методом Ньютона не было. Но затем выяснилось, что в некоторых случаях ( например, когда а3 и х после cubic очень близки ) уточнение необходимо. Константа 1е-3 выбрана произвольно.


Исходники находятся в mathem.zip.

AttachmentSize
mathem.zip12.18 KB
 

Comments

Post new comment

 
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.
By submitting this form, you accept the Mollom privacy policy.
Developed by NStudioCorp.com All trademarks and copyrights on this site are owned by their respective owners.
Comments are owned by the Poster. The Rest © 2000-2011 Firstov.com

About Firstov.com |  Terms of Service |  Support |  Contact Us |  Advertise