Recursive calculation of second order derivative
Recommendations:


Your output files are delimited by both spaces and tabs, which is weird.  You probably want to use tabs only.
There are a couple of points related to floating-point handling that I think deserve commenting:


Evaluating func(0.0) has a side effect of setting some floating-point error flags.
You actually intend to step x by Δx=0.01 between some lower bound and upper bound.  However, repeated addition of 0.01 would result in accumulation of round-off errors, so a workaround is used.

pow(x, 2) could be simplified to x * x.
Naming could be better.  I suggest:


pre → inv_delta_x (to emphasize its relationship to x)
fp → table, and fp2 → extrema (to explain the contents of the files)

Since you are already using C99-style comments, you should also take advantage of C99-style variable declarations, which allow you to declare variables closer to the point of use to enhance readability.


I've defined a FOR_RANGE() macro to make the loops in main() more readable, but that may be a controversial improvement.  I've also initialized min and max to INFINITY and -INFINITY, respectively, as a personal preference.

I agree that using recursion will probably yield unsatisfactory results, though I am unable to advise you further.  One of the comments above links to a related math question.  You will probably get a better answer about numerical methods on Computational Science SE.

#include &lt;math.h&gt;
#include &lt;stdio.h&gt;

// Singularity at x=0.0 raises exception FE_DIVBYZERO and/or sets errno to EDOM
float func(float x)
{
    return exp(x / 2) / (x * x);
}

#define FOR_RANGE(type, var, lower_bound, upper_bound, inv_delta) \
        for (type iteration_dummy = (lower_bound) * (inv_delta), var; \
             (var = iteration_dummy / (inv_delta)) &lt;= (upper_bound); \
             iteration_dummy++)

int main(void)
{
    // We want to increment x in steps of 0.01, but repeatedly adding 0.01
    // would cause round-off errors to accumulate.  Therefore, we will divide
    // successive floating-point integers by 100 instead.
    const float inv_delta_x = 100.0;

    FILE *table   = fopen("Q3data.dat", "w+"),
         *extrema = fopen("Q3results.dat", "w+");

    float min = INFINITY;
    FOR_RANGE(float, x, 0.0, 20.0, inv_delta_x)
    {
        float y = func(x);
        if (y &lt; min) min = y;
        fprintf(table, "%f\t%f\n", x, y);
    }

    fprintf(table, "\n\n");

    float max = -INFINITY;
    FOR_RANGE(float, x, -5.0, 5.0, inv_delta_x)
    {
        float y = func(x);
        float err;
        float nd1 = dfridr(func, x, 0.1, &amp;err); 
        float nd2 = dfridr2(x, 0.1);
        if (y &gt; max) max = y;
        fprintf(table, "%f\t%f\t%f\t%f\n", x, y, nd1, nd2);
    }

    fprintf(extrema, "The minimum value of f(x) is %f when x is between 0 and 20.\n", min);
    fprintf(extrema, "The maximum value of f(x) is %f when x is between -5 and 5.\n", max);
    fclose(table);
    fclose(extrema);
    return 0;
}