2014-11-27 2 views
5

Мне нужно решить кубическое уравнение (a x^3 + b x^2 + c * x + d = 0) аналитически и в действительных числах, предпочтительно в чистом javascript (no libs). Поскольку может быть от 1 до 3 корней, я думаю, что массив чисел является разумным типом результата.Функция для решения кубического уравнения аналитически

P.S. При условии, что мое собственное решение ниже, надейтесь, что это будет полезно.

+0

Сложные корни, а? – duffymo

+2

Этот вопрос кажется не по теме, потому что он просит других сделать вашу работу за вас. – duffymo

+0

@duffymo: Обратите внимание, что ответ один и тот же пользователь; он на самом деле делает эту работу и публикует ее здесь, я думаю, что вопрос просто кажется требованием. –

ответ

14

Здесь вы идете. Включает обработку дегенеративных случаев. Основной алгоритм в основном от wikipedia article.

function cuberoot(x) { 
    var y = Math.pow(Math.abs(x), 1/3); 
    return x < 0 ? -y : y; 
} 

function solveCubic(a, b, c, d) { 
    if (Math.abs(a) < 1e-8) { // Quadratic case, ax^2+bx+c=0 
     a = b; b = c; c = d; 
     if (Math.abs(a) < 1e-8) { // Linear case, ax+b=0 
      a = b; b = c; 
      if (Math.abs(a) < 1e-8) // Degenerate case 
       return []; 
      return [-b/a]; 
     } 

     var D = b*b - 4*a*c; 
     if (Math.abs(D) < 1e-8) 
      return [-b/(2*a)]; 
     else if (D > 0) 
      return [(-b+Math.sqrt(D))/(2*a), (-b-Math.sqrt(D))/(2*a)]; 
     return []; 
    } 

    // Convert to depressed cubic t^3+pt+q = 0 (subst x = t - b/3a) 
    var p = (3*a*c - b*b)/(3*a*a); 
    var q = (2*b*b*b - 9*a*b*c + 27*a*a*d)/(27*a*a*a); 
    var roots; 

    if (Math.abs(p) < 1e-8) { // p = 0 -> t^3 = -q -> t = -q^1/3 
     roots = [cuberoot(-q)]; 
    } else if (Math.abs(q) < 1e-8) { // q = 0 -> t^3 + pt = 0 -> t(t^2+p)=0 
     roots = [0].concat(p < 0 ? [Math.sqrt(-p), -Math.sqrt(-p)] : []); 
    } else { 
     var D = q*q/4 + p*p*p/27; 
     if (Math.abs(D) < 1e-8) {  // D = 0 -> two roots 
      roots = [-1.5*q/p, 3*q/p]; 
     } else if (D > 0) {    // Only one real root 
      var u = cuberoot(-q/2 - Math.sqrt(D)); 
      roots = [u - p/(3*u)]; 
     } else {      // D < 0, three roots, but needs to use complex numbers/trigonometric solution 
      var u = 2*Math.sqrt(-p/3); 
      var t = Math.acos(3*q/p/u)/3; // D < 0 implies p < 0 and acos argument in [-1..1] 
      var k = 2*Math.PI/3; 
      roots = [u*Math.cos(t), u*Math.cos(t-k), u*Math.cos(t-2*k)]; 
     } 
    } 

    // Convert back from depressed cubic 
    for (var i = 0; i < roots.length; i++) 
     roots[i] -= b/(3*a); 

    return roots; 
} 
+0

Реквизиты для письма это, при условии, что это работает! Я мог бы предложить вам отредактировать вопрос; Я думаю, что он привлекает downvotes, потому что он, кажется, требует ответа без работы, когда на самом деле вы предоставляете ответ здесь, и вы сделали работу! –

+0

Эпиплоны Hardcoding - плохая практика. –

Смежные вопросы