Численное дифференцирование

Как я могу вычислить числовую вторую производную функции, включающей экспоненту и сингулярность на бесконечности. К сожалению, числовая производная с помощью методов Риддера, представленных в «Численных рецептах в C», может вычислить только первую производную (для этого требуется предварительное аналитическое выражение функции). от фактических значений. Я также пробовал некоторые алгоритмы конечных разностей, представленные в математической статье, но они тоже были подвержены ошибкам. Функция равна e^(x/2)/x^2. Буду признателен за любую помощь в этом вопросе.

заранее спасибо

Последнее редактирование: проблема была решена, библиотеки FADBAD, доступные на C++, сделали очень хорошую работу. Они доступны через http://www.fadbad.com/fadbad.html.

РЕДАКТИРОВАТЬ:

// The compilation command used is given below
// gcc Q3.c nrutil.c DFRIDR.c -lm -o Q3

#include <stdio.h>
#include <math.h>
#include "nr.h"

#define LIM1 20.0
#define a -5.0
#define b 5.0
#define pre 100.0 // This defines the pre
/* This file calculates the func at given points, makes a 
 * plot. It also calculates the maximum and minimum of the func
 * at given points and its first and second numerical derivative.
*/
float func(float x)
{
    return exp(x / 2) / pow(x, 2);
}

int main(void)
{
    FILE *fp = fopen("Q3data.dat", "w+"), *fp2 = fopen("Q3results.dat", "w+");
    int i; // Declaring our loop variable
    float x, y, min, max, err, nd1, nd2;
    // Define the initial value of the func to be the minimum
    min = func(0); 
    for(i = 0; x < LIM1 ; i++)
    {   
        x = i / pre; // There is a singularity at x = 0 
        y = func(x);
        if(y < min)
            min = y;
        fprintf(fp, "%f \t %f \n", x, y);
    }
    fprintf(fp, "\n\n");
    max = 0;
    for(i = 0, x = a; x < b; i++)
    {   
        x = a + i / pre;
        y = func(x);
        nd1 = dfridr(func, x, 0.1, &err); 
        //nd2 = dfridr((*func), x, 0.1, &err);
        fprintf(fp, "%f \t %f \t %f \t %f \n", x, y, nd1);
        if(y > max)
            max = y;
    }

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

РЕДАКТИРОВАТЬ: Чебышев

// The compilation command used is given below
//gcc Q3.c nrutil.c CHEBEV.c CHEBFT.c CHDER.c -lm -o Q3


#include <stdio.h>
#include <math.h>
#include "nr.h"
#define NVAL 150 // Degree of Chebyshev polynomial
#define LIM1 20.0
#define a -5.0
#define b 5.0
#define pre 100.0 // This defines the pre
/* This file calculates the func at given points, makes a 
 * plot. It also calculates the maximum and minimum of the func
 * at given points and its first and second numerical derivative.
*/
float func(float x)
{
    return exp(x / 2) / pow(x, 2);
}

int main(void)
{
    FILE *fp = fopen("Q3data.dat", "w+"), *fp2 = fopen("Q3results.dat", "w+");
    int i; // Declaring our loop variable
    float x, y, min, max;
    float nd1, nd2, c[NVAL], cder[NVAL], cder2[NVAL];
    // Define the initial value of the func to be the minimum
    min = func(0); 

    for(i = 0; x < LIM1 ; i++)
    {   
        x = i / pre; // There is a singularity at x = 0 
        y = func(x);
        if(y < min)
            min = y;
        fprintf(fp, "%f \t %f \n", x, y);
    }
    fprintf(fp, "\n\n");
    max = 0;
    // We make a Chebyshev approximation to our function our interval of interest 
    // The purpose is to calculate the derivatives easily
    chebft(a,b,c,NVAL,func);
    //Evaluate the derivatives
    chder(a,b,c,cder,NVAL); // First order derivative
    chder(a,b,cder,cder2,NVAL); // Second order derivative
    for(i = 0, x = a; x < b; i++)
    {   
        x = a + i / pre;
        y = func(x);
        nd1 = chebev(a,b,cder,NVAL,x);
        nd2 = chebev(a,b,cder2,NVAL,x);

        fprintf(fp, "%f \t %f \t %f \t %f  \n", x, y, nd1, nd2);
        if(y > max)
            max = y;
    }

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

person Vesnog    schedule 11.01.2014    source источник
comment
Этот вопрос кажется не по теме, потому что он касается математики.   -  person Chris Laplante    schedule 12.01.2014
comment
@ChrisLaplante Я спросил об этом в категории численных методов, я думаю, что это очень актуально.   -  person Vesnog    schedule 12.01.2014
comment
Было бы полезно показать, что вы сделали, с помощью приближения Чебышева или конечной разницы. Алгоритмы могут быть правильными, но ваше кодирование может вызывать беспокойство, и SO может помочь в этом.   -  person chux - Reinstate Monica    schedule 12.01.2014
comment
@chux В любом случае я использовал процедуры числовых рецептов, я опубликую код, не раскрывая эти процедуры, поскольку они защищены авторским правом.   -  person Vesnog    schedule 12.01.2014
comment
@chux Я удалил свою реализацию алгоритмов конечных разностей после того, как получил большое количество ошибок.   -  person Vesnog    schedule 12.01.2014


Ответы (2)


Эта функция дифференцируема, поэтому использование числового метода, вероятно, не лучший вариант. Вторая производная:

6*exp(x/2)/(x^4)-2*exp(x/2)/x^3 + exp(x/2)/(4*x^2)

Вышеизложенное можно, конечно, упростить для ускорения вычислений. Изменить: в первый раз была неправильная исходная формула.

person evolvedmicrobe    schedule 11.01.2014
comment
Спасибо, но я думаю, что это дифференцируемо аналитически, но суть в том, чтобы использовать алгоритм для вычисления второй производной, не помогая компьютеру аналитически где-либо. Можно ли это сделать? - person Vesnog; 12.01.2014
comment
Да, это определенно можно сделать. Я предполагаю, что вы пробовали несколько рецептов, и они не работают, не зная точно, что вы пытаетесь использовать, было бы трудно комментировать, что не получается. - person evolvedmicrobe; 12.01.2014
comment
Тем не менее, как примечание, обычно код для поиска производных содержит много ошибок. дельта-Х). - person evolvedmicrobe; 12.01.2014
comment
Спасибо за ваше предложение. Я консультировался с процедурами из книги «Численные рецепты», и мне удалось вычислить вторую производную с помощью первой производной, оцененной в различных точках сетки. Для написания алгоритма я воспользовался статьей по математике о методах конечных разностей. - person Vesnog; 12.01.2014

Если вам нужен стопроцентный численный подход, посмотрите числовые рецепты интерполяции кубическим сплайном. (Статья 3.3). Это даст вам 2-ю производную в любом месте.

вызовите spline() со значениями x и y, чтобы вернуть вторые производные в y2. Вторая производная изменяется линейно в пределах каждого интервала. Итак, если, например, у вас есть

x      y      y2
0     10     -30
2      5     -15
4     -5     -10

тогда вторая производная в x=1 равна y2=-22.5, которая находится между -30 и -15.

вы также можете создать новую функцию splint() для возврата второй производной a*y2a[i]+b*y2a[i+1]

person John Alexiou    schedule 12.01.2014
comment
Спасибо, попробую этот подход. - person Vesnog; 12.01.2014
comment
К сожалению, этот подход дал результат inf во всех задействованных точках сетки. На самом деле я сослался на метод полиномиальной экстраполяции Риддерса (раздел 5.7). Он отлично работал для первой производной, и я смог оптимизировать его после прочтения главы, но для вычисления производной, как я уже упоминал, требуется аналитическое выражение для функции. Позже я объединил этот метод с методом конечных разностей, чтобы вычислить вторую производную от первой производной, вычисленной методом Риддерса. - person Vesnog; 12.01.2014