24
$\begingroup$

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

$\endgroup$
3
  • 1
    $\begingroup$ 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. $\endgroup$
    – Sunday
    Apr 9, 2013 at 15:46
  • 3
    $\begingroup$ 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. $\endgroup$ Apr 9, 2013 at 16:02
  • $\begingroup$ There is such a function in the "Presentations" package of David Park home.comcast.net/~djmpark/index.html $\endgroup$ May 18, 2015 at 12:33

11 Answers 11

35
$\begingroup$

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
$\endgroup$
4
  • 1
    $\begingroup$ Nice generalization. +1 $\endgroup$
    – Mr.Wizard
    Apr 10, 2013 at 11:13
  • 3
    $\begingroup$ It looks like there will be a lot of polynomials out there requiring meds after your pogrom of depression. (+1) $\endgroup$
    – rcollyer
    Apr 10, 2013 at 12:59
  • 1
    $\begingroup$ @rcollyer: the mathematicians talk about polynomial "lifting" too; I suppose that's the proper thing to do afterwards... $\endgroup$ Apr 10, 2013 at 13:08
  • 7
    $\begingroup$ 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! $\endgroup$
    – rcollyer
    Apr 10, 2013 at 13:16
6
$\begingroup$

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
$\endgroup$
5
$\begingroup$

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.

$\endgroup$
6
  • 1
    $\begingroup$ It is a buried but valuable answer $\endgroup$
    – yode
    Oct 13, 2021 at 9:55
  • $\begingroup$ What is AlphaScannerFunctions? I've done extencive Google has no idea. $\endgroup$
    – Anton
    Aug 23 at 17:44
  • $\begingroup$ @Anton It is a package/context that contains some functions. CompleteSquare showed up when I searched for it (something like ? *`*CompleteSquare*). $\endgroup$
    – Michael E2
    Aug 23 at 18:09
  • $\begingroup$ @MichaelE2 gotcha $\endgroup$
    – Anton
    Aug 23 at 18:28
  • $\begingroup$ @MichaelE2 i see. But, how do I use it? AlphaScannerFunctions`CompleteSquare[5 x^2 + 27 x == 5, x] does nothing ( $\endgroup$
    – Anton
    Aug 23 at 18:36
3
$\begingroup$

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
$\endgroup$
3
$\begingroup$
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}
*)
$\endgroup$
2
$\begingroup$

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}
$\endgroup$
2
$\begingroup$

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.

$\endgroup$
2
$\begingroup$

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)
   }
 ];
$\endgroup$
2
  • $\begingroup$ I think it is quite readable. Is there any guru around who could elaborate a bit about the different solutions and whether they are equivalent or where they differ? $\endgroup$
    – Sunday
    Apr 10, 2013 at 8:51
  • 2
    $\begingroup$ You might want to look into CoefficientList[], which gives all the coefficients in one blow. $\endgroup$ Apr 10, 2013 at 11:04
2
$\begingroup$

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 *)
$\endgroup$
8
  • $\begingroup$ Which doesn't work always ... $\endgroup$
    – BoLe
    Apr 10, 2013 at 9:53
  • $\begingroup$ Edited, with a optional pattern _. that can be missing from the expression, via @RunnyKine. $\endgroup$
    – BoLe
    Apr 10, 2013 at 10:00
  • $\begingroup$ 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] $\endgroup$
    – Mr.Wizard
    Apr 10, 2013 at 11:12
  • $\begingroup$ 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? $\endgroup$
    – BoLe
    Apr 10, 2013 at 11:57
  • 2
    $\begingroup$ 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 $\endgroup$
    – Mr.Wizard
    Apr 10, 2013 at 12:13
2
$\begingroup$

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
$\endgroup$
1
$\begingroup$

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.

$\endgroup$
2
  • 2
    $\begingroup$ You might want to localize a, b, and c in Module, too. (One can also assign them values with {c, b, a} = cba;, which looks cute.) $\endgroup$
    – Michael E2
    Aug 7, 2021 at 23:06
  • $\begingroup$ Thank you for the suggestions! $\endgroup$
    – Charles
    Aug 9, 2021 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.