Решение кубического уравнения O(logN)



a * x3 + b * x2 + c * x + d = 0

    Пусть f(x) = a * x3 + b * x2 + c * x + d = 0,
тогда f'(x) = 3 * a * x2 + 2 * b * x + c, найдём критические точки.
    Функция в области между критическими точками монотонно возрастает или убывает. Поэтому уравнение на этих отрезках можно решить с помощью бинарного поиска.


Листинг C++

int sign (double x)
{
    return eq (x, 0) ? 0 : x < 0 ? - 1 : 1;
}

bool cubic_binfind (double l, double r, double a, double b, double c, double d, double & x)
{
    double fl = ((a * l + b) * l + c) * l + d;
    double fr = ((a * r + b) * r + c) * r + d;
    if (sign (fl) == 0)
    {
        x = l;
        return 1;
    }
    if (sign (fr) == 0)
    {
        x = r;
        return 1;
    }
    if (sign (fl) == sign (fr))
        return 0;
    
    
    while (r - l > eps / 1000.000)
    {
        double mid = 0.500 * (l + r);
        
        double fmid = ((a * mid + b) * mid + c) * mid + d;
        
        if (sign (fmid) == 0)
        {
            x = mid;
            return 1;
        }
        
        if (sign (fmid) == sign (fr))
            r = mid;
        else
            l = mid;
    }
    
    x = 0.5 * (r + l);
    
    return 1;
}

int cubic_equation (double a, double b, double c, double d, double & x1, double & x2, double & x3)
{
    if (eq (a, 0))
        return sqr_equation (b, c, d, x1, x2);
    
    double xk1, xk2;    // критические точки функции f(x) = ax^3 + bx^2 + cx + d
    int cnt = sqr_equation (3.000 * a, 2.000 * b, c, xk1, xk2);
    if (cnt == 1)
        xk2 = xk1;
    if (cnt == 0)
        xk2 = xk1 = 0;
    
    double left = - inf;
    double right = inf;
    
    double xp1, xp2, xp3;
    int c1 = cubic_binfind (left, xk1, a, b, c, d, xp1);
    int c2 = cubic_binfind (xk1, xk2, a, b, c, d, xp2);
    int c3 = cubic_binfind (xk2, right, a, b, c, d, xp3);
    
    if (c1)
        x1 = xp1;
    if (c2)
        if (c1)
            x2 = xp2;
        else
            x1 = xp2;
    
    if (c3)
        if (c2)
            if (c1)
                x3 = xp3;
            else
                x2 = xp3;
        else
            if (c1)
                x2 = xp3;
            else
                x1 = xp3;
    
    return c1 + c2 + c3;
}

14:57
06.08.2009



По всем вопросам обращаться: rumterg@gmail.com