I have numbers in vector notation. I need to get polynomial notation from them.
My numbers are {0, 1, 23, 5, 15, 0, 0, 0}
. I want to get $x + 23x^2 + 5x^3 + 15x^4$ from this list.
How can I get that polynomial?
I have numbers in vector notation. I need to get polynomial notation from them.
My numbers are {0, 1, 23, 5, 15, 0, 0, 0}
. I want to get $x + 23x^2 + 5x^3 + 15x^4$ from this list.
How can I get that polynomial?
One straightforward approach is to calculate the answer directly:
Total[{0, 1, 23, 5, 15, 0, 0, 0} x^(Range[8] - 1)]
The following (taken from the Mathematica documentation) will do what you ask.
Expand[FromDigits[Reverse[{0, 1, 23, 5, 15, 0, 0, 0}], x]]
x + 23 x^2 + 5 x^3 + 15 x^4
I found the needed code in Properties & Relations section of the documentation page on CoefficientList
. In general, it is a good idea to look for information on inverses in the Properties & Relations section of any function of interest.
The undocumented function Internal`FromCoefficientList
is as close as one would get to InverseCoefficientList
.
Examples:
cl = {0, 1, 23, 5, 15, 0, 0, 0};
Internal`FromCoefficientList[cl, x]
x + 23 x^2 + 5 x^3 + 15 x^4
cl2 = CoefficientList[(1 + x + 2 y)^2, {x, y}]
{{1, 4, 4}, {2, 4, 0}, {1, 0, 0}}
FullSimplify[Internal`FromCoefficientList[cl2, {x, y}]]
(1 + x + 2 y)^2
See also: this answer by Adam Strzebonski (thanks: Mr. Wizard for the reference)
Timings using @Mr.Wizard's set-up and timeAvg
:
n = 5000;
c = RandomInteger[30, n];
Expand[Fold[(#1 \[FormalX] + #2) &, 0, Reverse[c]]] // timeAvg (* 3.250000 *)
Expand@FromDigits[Reverse@c, x] // timeAvg (* 0.039375 *)
MapIndexed[#1*x^(#2 - 1) &, c] // Total // timeAvg (* 0.019375 *)
Total[c*x^(Range@n - 1)] // timeAvg (* 0.005375 *)
c.(x^Range[0, n - 1]) // timeAvg (* 0.003875 *)
Internal`FromCoefficientList[c, x] // timeAvg (* 0.003500 *)
rules = (#2 - {1}) -> #1 & @@@ MapIndexed[Rule, cl]; FromCoefficientRules[rules, x]
.
$\endgroup$
Dot
can be very efficient here:
c.(x^Range[0, Length@c - 1])
x + 23 x^2 + 5 x^3 + 15 x^4
Comparative timings:
n = 5000;
c = RandomInteger[30, n];
SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}]
Expand @ FromDigits[Reverse@c, x] // timeAvg
Total[c * x^(Range@n - 1)] // timeAvg
MapIndexed[#1*x^(#2 - 1) &, c] // Total // timeAvg
c.(x^Range[0, n - 1]) // timeAvg
0.03616
0.004992
0.01744
0.003616
I also like this formulation though it is not quite as fast:
c.Array[x^# &, n, 0]
I vastly prefer using Horner for reconstructing polynomials from their coefficients. To wit:
Fold[(#1 \[FormalX] + #2) &, 0, Reverse[{0, 1, 23, 5, 15, 0, 0, 0}]] // Expand
returns your polynomial. In fact, this is effectively what FromDigits[]
does internally for integer digits. Removing the Expand[]
yields what would've been the result of applying HornerForm[]
to the polynomial.
Fold[]
, old habits, I guess (I still don't have a computer, much less version 10). Anyway, as I said, this is what is done internally in FromDigits[]
; I thought it'd be a nice showcase for Horner. As is well-known, Horner minimizes the number of multiplications necessary for evaluating a polynomial, in contrast to an explicit monomial expansion.
$\endgroup$
Commented
May 10, 2015 at 14:00
How about this?
MapIndexed[#1*x^(#2 - 1) &, {0, 1, 23, 5, 15, 0, 0, 0}] // Total
(* {x + 23 x^2 + 5 x^3 + 15 x^4} *)
mycoeff = {0, 1, 23, 5, 15, 0, 0, 0};
FromCoeff[lst_, x_]:=Plus@@(lst*x^(Part/@Range[Length[lst]]-1));
FromCoeff[mycoeff, x]
Part /@ Range[Length[lst]]
does not make sense.
$\endgroup$
Commented
Aug 14, 2015 at 0:16
Part/@
appears vestigial. Also you are pretty much duplicating bill's Accepted answer. :-/
$\endgroup$
Commented
Aug 14, 2015 at 15:08