Answer
Here is an alternative approach, leveraging Mathematica's intelligent plotting algorithms. The basic idea is to use the list of points evaluated when plotting the function.
Suppose I want the roots between 0 and 1400. Plot the function and assign the plot to a variable (I won't display the plot here):
eq[n_, β_, λ_] = Hypergeometric1F1[1/4 (2 - λ/β), n + 1, β];
p = Plot[eq[1, 1, λ], {λ, 0, 1400}];
Extract the actual list of points from the plot:
points = p[[1, 1, 3, 3, 1]];
This looks like this:
points // Shallow
so it is the actual list of points used by Plot
. You could for instance ListLinePlot
them and get something like Plot
would give.
Now, the idea is to inspect this list, note when the $y$ coordinate changes sign between neighbouring points, and use the $x$ coordinate as the initial value for FindRoot
. Clearly, this does not guarantee that we'll get the root nearest that point, but it usually works.
Here is how to locate where neighbouring points change sign: First pair up the neighbours:
pairs = Partition[points[[All, 2]], 2, 1];
then here is where the signs of neighbouring $y$-coordinates change:
flips = Position[Sign[Times @@ # & /@ pairs],-1];
and now find the roots:
roots=λ /. FindRoot[eq[1, 1, λ],
{λ,
First@First@points[[#]],
First@First@points[[1 + #]]
}] & /@ flips
And it works:
Show[
p,
Graphics@{Red, PointSize[Large],
Point[Partition[Riffle[roots, 0], 2]]}
]
(the last root is correctly calculated, but I was too lazy to plot it).
Comments
We didn't have to use Plot
to extract the points; we could have just constructed a list of values at equidistant points using Table
, say. I chose Plot
because sometimes its adaptive stepsizes can be useful.
This method has the advantage that it requires less detailed knowledge than e.g. J.M.'s approach, and it may be more efficient than Vitaliy's method.
Please note that this method is also described here and, apparently, in a book by Stan Wagon (also mentioned in the answer linked to).