Numerical underflow for a scaled error function

If you have an analytic formula for f[x_] := Erfc[x]*Exp[x^2] not using Erfc[x] you could do what you expect. However it is somewhat problematic to do in this form because Erfc[x] < $MinNumber for x == 27300.

$MinNumber
1.887662394852454*10^-323228468
N[Erfc[27280.], 20]
5.680044213569341*10^-323201264

Edit

A very good approximation of your function f[x] for values x > 27280 you can get making use of these bounds ( see e.g. Erfc on Mathworld) :

enter image description here

which hold for x > 0.

Here we find values of the lower and upper bounds with relative errors for various x:

T = Table[ 
          N[#, 15]& @ {2 /(Sqrt[Pi] (x + Sqrt[2 + x^2])), 
                       2 /(Sqrt[Pi] ( x + Sqrt[x^2 + 4/Pi])), 
                       1 - ( x + Sqrt[x^2 + 4/Pi])/(x + Sqrt[2 + x^2]),
          {x, 30000 Table[10^k, {k, 0, 5}]}];

Grid[ Array[ InputField[ Dynamic[T[[#1, #2]]], FieldSize -> 13] &, {6, 3}]]

enter image description here

Therefore we propose this definition of the function f (namely the arithetic mean of its bounds for x > 27280 ) :

f[x_]/; x >= 0 := Piecewise[ { { Erfc[x]*Exp[x^2],                      x < 27280 },

                               { 1 /( Sqrt[Pi] ( x + Sqrt[2 + x^2])) 
                               + 1 /( Sqrt[Pi] ( x + Sqrt[x^2 + 4/Pi])), x >= 27280}}
                           ]
f[x_] /; x < 0 := 2 - f[-x]

I.e. we use the original definition of the function f for 0 < x < 27280, the approximation for x > 27280 and for x < 0 we use the known symmetry of the Erfc function, which is relevant when we'd like to calculate f[x] for x < - 27280. Now we can safely use this new definition for a much larger domain :

{f[300], f[300.], f[30000.], f[-30000.]}
{E^90000 Erfc[300], 0.0018806214974, 0.0000188063, 1.99998}

and now we can make plots of f around of the gluing point ( x = 27280.)

GraphicsRow[{ Plot[ f[x], {x, 2000, 55000}, 
                      Epilog -> {PointSize[0.02], Red, Point[{27280., f[27280.]}]}, 
                      PlotStyle -> Thick, AxesOrigin -> {0, 0}], 
              Plot[ f[x], {x, 27270, 27290}, 
                      Epilog -> {PointSize[0.02], Red, Point[{27280., f[27280.]}]}, 
                      PlotStyle -> Thick]}]

enter image description here


I've had to work with that kind of function (relying on cancellation of large terms) before, and the most practical workaround I could figure out to be able to evaluate the function numerically is to use its power expansion near the point of trouble (here, $+\infty$).

So, get a good look at the series expansion and find out how it works (or derive it on paper):

Series[f[x], {x, ∞, 50}]

So, that means that you can use

$$f(x) \approx \sum_{n=0}^N \left(-\frac{1}{2}\right)^n \frac{(2n-1)!!}{x^{2n+1}}$$

for $x$ larger than some value $X$. All that remains is to find a couple of values $(X,N)$ suitable to your needs. Because we have a series with signs alternating and terms decrease, the error is bounded by the $(n+1)$th term. Assuming we want to choose a value of $X$ in the range [20,1000], we plot the relative error after the $N$th term as a function of $x$ in this range:

LogLogPlot[Table[(2 n - 1)!!/x^(2 n + 1)/f[x], {n, 5, 10}], {x, 20, 1000}]

enter image description here

So, say we want to have a relative accuracy of $10^{-30}$ (which is better than machine precision), we can for example take $X=100$ and $N=10$. This gives us the following definition for your f function:

f[x_] := Piecewise[{{Erfc[x]*Exp[x^2], x < 100}}, 
   1/Sqrt[π]*Sum[(-1/2)^n*(2 n - 1)!!/x^(2 n + 1), {n, 0, 10}]];

LogLogPlot[{f[x], Erfc[x]*Exp[x^2]}, {x, 10, 10^6}, 
 PlotStyle -> {Red, Directive[Blue, Thick, Opacity[0.4]]}]

enter image description here


For numerical evaluation, there is the rapidly-converging continued fraction (due to Jones and Thron):

$$\exp(x^2)\mathrm{erfc}(x)=\frac{2x}{\sqrt \pi}\cfrac{1}{2x^2+1-\cfrac{1\cdot2}{2x^2+5-\cfrac{3\cdot4}{2x^2+9-\cdots}}},\qquad x > 0$$

One can use the built-in function ContinuedFractionK[] with a suitable cut-off:

With[{x = N[30000], n = 10}, -2 x /(1 + 2 x^2 + 
      ContinuedFractionK[2 j (1 - 2 j), 1 + 4 j + 2 x^2, {j, 1, n}])/
   Sqrt[Pi]]
0.0000188063

or, even better, use the Lentz-Thompson-Barnett algorithm for evaluating this continued fraction, avoiding unneeded evaluation effort:

f[z_?InexactNumberQ] := Module[{c, d, h, k, u, v, y},
   y = v = 2 z^2 + 1;
   c = y; d = 0; k = 1;
   While[True,
    u = k (k + 1); v += 4;
    c = v - u/c; d = 1/(v - u d);
    h = c*d; y *= h;
    If[Abs[h - 1] <= 10^-Precision[z], Break[]];
    k += 2];
   2 z/y/Sqrt[Pi]] /; Re[z] > 0

With[{z = N[50]}, {Exp[z^2] Erfc[z], f[z]}]
{0.01128153626532, 0.0112815}

N[f[30000], 30]
0.0000188063194411439209981315314042

Plot[f[x], {x, 1, 50}]

plot of exp(x^2)erfc(x)