25

How can I write a function that would complete the square in a quadratic polynomial expression such that, for example,

CompleteTheSquare[5 x^2 + 27 x - 5, x]

evaluates to

-(829/20) + 5 (27/10 + x)^2

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
Sunday
  • 413
  • 5
  • 7
  • 1
    I already have a solution that I want to discuss and maybe improve. I will post it in 8+ hours as soon as I am allowed to. – Sunday Apr 09 '13 at 15:46
  • 3
    This is a special case (and therefore a duplicate) of this one. I am not voting to close right now given your desire to post and discuss your solution. – Leonid Shifrin Apr 09 '13 at 16:02
  • There is such a function in the "Presentations" package of David Park http://home.comcast.net/~djmpark/index.html – Alexei Boulbitch May 18 '15 at 12:33

11 Answers11

36

I was waiting for OP to post his answer before posting mine. In any event, here's a general routine for performing polynomial depression (where completing the square corresponds to the quadratic case):

depress[poly_] := depress[poly, First@Variables[poly]]

depress[poly_, x_] /; PolynomialQ[poly, x] := Module[{n = Exponent[poly, x], x0},
        x0 = -Coefficient[poly, x, n - 1]/(n Coefficient[poly, x, n]);
        Normal[Series[poly, {x, x0, n}]]]

Examples:

depress[5 x^2 + 27 x - 5]
   -(829/20) + 5 (27/10 + x)^2

depress[2 x^3 - 7 x^2 + 19 x - 4]
   319/27 + 65/6 (-(7/6) + x) + 2 (-(7/6) + x)^3
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
  • 1
    Nice generalization. +1 – Mr.Wizard Apr 10 '13 at 11:13
  • 3
    It looks like there will be a lot of polynomials out there requiring meds after your pogrom of depression. (+1) – rcollyer Apr 10 '13 at 12:59
  • 1
    @rcollyer: the mathematicians talk about polynomial "lifting" too; I suppose that's the proper thing to do afterwards... – J. M.'s missing motivation Apr 10 '13 at 13:08
  • 7
    First you depress them, then you lift them. Sounds like a cycle of abuse to me. When will the senseless polynomial abuse stop?!? Before you know it, there will be free radicals roaming about trying to cause havoc! – rcollyer Apr 10 '13 at 13:16
6

Here's a quick version that uses the matrix approach to completing the square and works for any dimension. It has a couple of checks to make sure that the input is sane, but could have more.

CompleteTheSquare::notquad = "The expression is not quadratic in the variables `1`";
CompleteTheSquare[expr_] := CompleteTheSquare[expr, Variables[expr]]
CompleteTheSquare[expr_, Vars_Symbol] := CompleteTheSquare[expr, {Vars}]
CompleteTheSquare[expr_, Vars : {__Symbol}] := Module[{array, A, B, C, s, vars, sVars},
  vars = Intersection[Vars, Variables[expr]];
  Check[array = CoefficientArrays[expr, vars], Return[expr], CoefficientArrays::poly];
  If[Length[array] != 3, Message[CompleteTheSquare::notquad, vars]; Return[expr]];
  {C, B, A} = array; A = Symmetrize[A];
  s = Simplify[1/2 Inverse[A].B, Trig -> False];
  sVars = Hold /@ (vars + s); A = Map[Hold, A, {2}];
  Expand[A.sVars.sVars] + Simplify[C - s.A.s, Trig -> False] // ReleaseHold
  ]

For example:

In[]:= CompleteTheSquare[a x^2 + b x + c y^2 + d y, {x, y}]

Out[]= -((a b^2 c^2 + a^2 c d^2)/(4 a^2 c^2)) + a (b/(2 a) + x)^2 + c (d/(2 c) + y)^2
Simon
  • 10,167
  • 5
  • 57
  • 72
5

There's a ResourceFunction for this since 9 Aug 2019:

cs = ResourceFunction["CompleteTheSquare"]

cs[5 x^2 + 27 x - 5, x] (* -(829/20) + 5 (27/10 + x)^2 *)

cs[5 x^2 + 27 x == 5, x] (* -(829/20) + 5 (27/10 + x)^2 *)

And, oddly, a helper for ResourceFunction that does nearly the same thing:

ResourceFunctionHelpers`CompleteSquare[5 x^2 + 27 x - 5, x]
(*  -(829/20) + 5 (27/10 + x)^2  *)

ResourceFunctionHelpers`CompleteSquare[5 x^2 + 27 x == 5, x] (* -(829/20) + 5 (27/10 + x)^2 == 0 *)

Also, AlphaScannerFunctions`CompleteSquare does the same thing.

Michael E2
  • 235,386
  • 17
  • 334
  • 747
3
cts[pol_,var_]:= Module[{a, b, c}, 
                        b (a + var)^2 + c /.
                        Solve[ForAll[var, pol == b (a + var)^2 + c], {a, b, c}]]

cts[5 x^2 + 27 x - 5, x]
(*
{-(829/20) + 5 (27/10 + x)^2}
*)

and the general solution is of course:

cts[a x^2 + b x + c, x]
(*
{(-b^2 + 4 a c)/(4 a) + a (b/(2 a) + x)^2}
*)
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Dr. belisarius
  • 115,881
  • 13
  • 203
  • 453
3

Here's my take:

CompleteTheSquare[a_. x_^2 + b_ x_ + c_, x_] := 
 a (x - (-b/(2 a)))^2 + (c - b^2/(4 a))

Note the dot after the a_, for cases where a is 1.

CompleteTheSquare[5 x^2 + 27 x - 5, x]

gives

-(829/20) + 5 (27/10 + x)^2
RunnyKine
  • 33,088
  • 3
  • 109
  • 176
2

You can work out the general form of the coefficients but here's one implementation:

completeTheSquare[p_, x_] := 
 Module[{a, b, c}, (a ( x + b)^2 + c) /. 
   Solve[Thread[
     CoefficientList[Expand[a ( x + b)^2 + c], x] == 
      CoefficientList[p, x]], {a, b, c}]]

completeTheSquare[12 x^2 + 2 x - 7, x]
(*out*){-(85/12) + 12 (1/12 + x)^2}

completeTheSquare[5 x^2 + 27 x - 5, x]
(*out*){-(829/20) + 5 (27/10 + x)^2}
gpap
  • 9,707
  • 3
  • 24
  • 66
2

Strictly speaking, the following doesn't reveal how to code completing the square. But if you have David Park's Presentations add-on (see http://home.comcast.net/~djmpark/DrawGraphicsPage.html), then you can do:

   <<Presentations`

   CompleteTheSquare[2 x^2 - 3 x + 5, x]
(*  31/8 + 2*(-3/4 + x)^2  *)

And if you look into the Manipulations package within Presentations, you'll find the code for Park's CompleteTheSquare.

murray
  • 11,888
  • 2
  • 26
  • 50
2

this is my own solution:

CompleteTheSquare[e_, x_] := Module[{a, b, c, B, C},
   a (x + B)^2 + C //. {
     a -> Coefficient[e, x, 2], 
     b -> Coefficient[e, x, 1],
     c -> Coefficient[e, x, 0], 
     B -> b/(2 a), 
     C -> c - b^2/(4 a)
   }
 ];
Sunday
  • 413
  • 5
  • 7
2

Storing the general solution as a rule and applying it to expression. (Rule edited after consultation with @Mr.Wizard.)

complete = a_. x_Symbol^2 + b_. x_Symbol + c_. :>
   a (x + b/(2 a))^2 - b^2/(4 a) + c;

Sqrt[5]^2 u^2 + 27 u - 5 /. complete

(* -(829/20) + 5 (27/10 + u)^2 *)
BoLe
  • 5,819
  • 15
  • 33
  • Which doesn't work always ... – BoLe Apr 10 '13 at 09:53
  • Edited, with a optional pattern _. that can be missing from the expression, via @RunnyKine. – BoLe Apr 10 '13 at 10:00
  • I believe a, b, and c should be localized (:>). Also, shouldn't x be a parameter? Perhaps something like this?: complete = a_. #^2 + b_. # + c_. :> a (# + b/(2 a))^2 - b^2/(4 a) + c &; then: 5 x^2 + 27 x - 5 /. complete[x] – Mr.Wizard Apr 10 '13 at 11:12
  • I agree about x -- is it just for the case of an arbitrarily named variable? I don't really know about the rule; I can understand -> vs. :> in a case like {{1, 2}, {1, 3}, {1, 5}} /. {i_, j_} -> {i, RandomReal[]} but what's the difference here? – BoLe Apr 10 '13 at 11:57
  • 2
    Rule does not localize symbols while RuleDelayed does. Using your code as written start with a = b = c = "Fail"; and you will get (3 "Fail")/4 + "Fail" (1/2 + x)^2; change only -> to :> and you get -(829/20) + 5 (27/10 + x)^2 – Mr.Wizard Apr 10 '13 at 12:13
  • BoLe why not update your answer? I'd like to vote for it, but not in its present state. – Mr.Wizard Apr 12 '13 at 18:12
  • @Mr.Wizard Localization, right. I didn't make it as a pure function though, instead I'm relying on an assumption that only a variable headed Symbol will appear in ^2 form. Is there a hole in this logic? Or else: vote me up, please. :) – BoLe Apr 12 '13 at 20:53
  • You've got my vote. :-) – Mr.Wizard Apr 12 '13 at 23:46
2

Here is my solution. completeSq calls itself recursively until there is no change.

completeSq[a_. x_^2 + b_. x_ + c_: 0] := -(b^2/(4 a)) + 
  a (b/(2 a) + x)^2 + completeSq[c]
completeSq[d_] := d

It even works with complex real numbers:

In[236]:= completeSq[
 4.1 + z^2 + 2 x + I x^2 + 10 y + -3 x - 12 y^2 + 5.1 z + z^2]

Out[236]= (2.93208 + 0.25 I) + I (I/2 + x)^2 - 12 (-(5/12) + y)^2 + 
 2 (1.275 + z)^2
Maritimer
  • 171
  • 1
  • 4
1

I know this question is pretty old but I want to add a possible solution that I think is simple and worth sharing:

CompleteTheSquare[poly_,x_] := Module[                                          
  {cba = CoefficientList[poly, x]},                                             
  c = cba[[1]];                                                                 
  b = cba[[2]];                                                                 
  a = cba[[3]];                                                                 
  a(x+b/(2a))^2+(c-b^2/(4a))                                                                    
  ]

It is a simple implementation of the algorithm for completing the square.

Charles
  • 11
  • 1