5

I'm trying to obtain an interpolation function for points of an x^(-5) function (which goes to infinity at x = 0).

hyper = Flatten[Table[[x^(-5)], {x, 1, 100}]];
points = Range[100];

data = Transpose@{points, hyper}

If I do a ListPlot of data, I have:

List Plot of the x^(-5) function

If I use interpolation like:

Interpolation[data, Method -> "Spline"]
Interpolation[data, Method -> "Hermite"]

I get an interpolating function with this form:

Interpolating function with the ListPlot points

Clearly, the interpolation function has not the simplest form for 'joining' those points, since it has an uprising between x = 3 and x = 4, and an oscillatory behavior.

My question is: Can I make some kind of interpolation to data which reproduces the form of the true function, without those oscillations?

In particular, I'm interested in get an appropriate value of the interpolating function at x = 3.68, for example.

Thanks for the answers.

3 Answers3

10

In this case, the data are very unlike a polynomial, thus ill-suited for polynomial interpolation. On the other hand, the inverse data represent a polynomial, so interpolate them:

invdata = Transpose@{points, 1/hyper};
invinterp = Interpolation[invdata]
Plot[1/invinterp[x], {x, 1, 10}]

enter image description here

In general, the art of polynomial approximation and interpolation involves invertable transformations that put your functions into something whose trajectory resembles a polynomial.

John Doty
  • 13,712
  • 1
  • 22
  • 42
3

If the function's derivative is easy to obtain, then the default piecewise interpolation works fairly well when the derivative values are specified.
One can also use FunctionInterpolation. With FunctionInterpolation you can adjust the options to achieve a desired accuracy.

f = x^-5;
df = D[f, x];
data = Table[{{x}, f, df}, {x, 1., 100.}];
ifn1 = Interpolation[data];

ifn2 = FunctionInterpolation[x^(-5), {x, 1., 100.}]; (* complains... *)

FunctionInterpolation::ncvb: FunctionInterpolation failed to meet the prescribed accuracy and precision goals after 6 recursive bisections near x = {1.}. Continuing to refine elsewhere. >>

ifn3 = FunctionInterpolation[x^(-5), {x, 1., 100.},               (* use options to fix *)
   MaxRecursion -> 16, PrecisionGoal -> 12, AccuracyGoal -> 14];  (* as desired *)

Comparison of error of the three methods:

Plot[x^(-5) - {ifn1[x], ifn2[x], ifn3[x]} // RealExponent // Evaluate,
 {x, 1, 100}, PlotRange -> All, 
 PlotLegends -> {"ifn1", "ifn2", "ifn3"}]

Mathematica graphics

Michael E2
  • 235,386
  • 17
  • 334
  • 747
1

You can just sample your function on a finer grid. Using grid spacing of 1, like you are, leads to horrible interpolation, whereas a grid spacing of 0.1 works out perfectly.

(data = Table[{x, x^-5}, {x, 1, 100, #}];
   Show[
    Plot[Interpolation[data, InterpolationOrder -> 3][x], {x, 1, 10}, 
     PlotRange -> All, ImageSize -> 400], ListPlot[data], 
    PlotRange -> {{1, 10}, All}
    ]
   ) & /@ {1, .5, .1}

Mathematica graphics

For a function like this though, it is actually better to sample on a finer grid in a region where the value changes quickly, and on a sparser grid where it changes slowly. You can look at the grid that FunctionInterpolation comes up with after its recursions:

fn = FunctionInterpolation[x^-5, {x, 1, 100}];
fn[[3]]
ListPlot@%

Mathematica graphics

Jason B.
  • 68,381
  • 3
  • 139
  • 286