С. вычисление градиента функции многих переменных

введите сюда описание изображения

введите сюда описание изображения

Попыталась следовать следующему алгоритму

введите сюда описание изображения

изначальный вариант выглядел так

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <locale.h>
double f(double x)
{
    return (x * x );
}
int main(int argc, char** argv) {
    double del = 0.1;
    int n;
    scanf_s("%d", &n);
    double* x;
    x = (double*)malloc(n * sizeof(double));
    double* y;
    y = (double*)malloc(n * sizeof(double));
    double* fx;
    fx = (double*)malloc(n * sizeof(double));
    double* fy;
    fy = (double*)malloc(n * sizeof(double));
    double* grad;
    grad = (double*)malloc(n * sizeof(double));
    int i = 0;
    for (i = 0; i < n; i++)
    {
        printf("x[%d] = ", i);
        scanf_s("%lf", &x[i]);
        y[i] = x[i];
        fx[i] = f(x[i]);
    }
    double a = 1 / del;
    for (i = 0; i < n; i++) {
        y[i] = y[i] + del;
        fy[i] = f(y[i]);
        grad[i] = a * (fy[i] - fx[i]);
        y[i] = x[i];

    }
    for (i = 0; i < n; i++) {
    printf("%lf ", grad[i]);
    }

}

Затем я поняла, что должна передавать массив в качестве аргумента в функцию. Но так и не поняла, как сделать это правильно.(выводится мусор) И необходимость в массивах fx и fy...которой, вероятно, нет. Пожалуйста , помогите откорректировать , т.к. понимаю, что наверняка есть косяк в моей реализации алгоритма. К сожалению, я даже не понимаю какие входные данные я должна подавать и какой результат должна выдавать корректно работающая программа. Я очень буду благодарна за помощь, очень хочу разобраться в этом, но пока на этом моменте застопорилась....

double f(double arr[], int size)
{
    int a = sizeof(arr);
    for (int i = 0; i < size; i++) {
        arr[i] = arr[i] * arr[i];
    }
    return *arr;
}
int main(int argc, char** argv) {
    double del = 0.1;
    int n;
    scanf_s("%d", &n);
    double* x;
    x = (double*)malloc(n * sizeof(double));
    double* y;
    y = (double*)malloc(n * sizeof(double));
    double* fx;
    fx = (double*)malloc(n * sizeof(double));
    double* fy;
    fy = (double*)malloc(n * sizeof(double));
    double* grad;
    grad = (double*)malloc(n * sizeof(double));
    int i = 0;
    for (i = 0; i < n; i++)
    {
        printf("x[%d] = ", i);
        scanf_s("%lf", &x[i]);
        y[i] = x[i];
        fx[i] = f(x,n);
    }
    double a = 1 / del;
    for (i = 0; i < n; i++) {
        y[i] = y[i] + del;
        fy[i] = f(y,n);
        grad[i] = a * (fy[i] - fx[i]);
        y[i] = x[i];

    }
    for (i = 0; i < n; i++) {
    printf("%lf ", grad[i]);
    }

}

Вариант Mikhailo (изменен):

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <locale.h>


void grad(double* y,    // Возвращаемый массив
    double* x,    // Точка, в которой вычисляется градиент
    int n,        // Число переменных
    double d,     // Та самая дельта
    double (*f)(double*, int)) { // Исследуемая функция
    double f0 = f(x, n);
    for (int i = 0; i < n; ++i) {
        double save = x[i];
        x[i] += d;
        double f1 = f(x, n);
        x[i] = save;
        y[i] = (f1 - f0) / d;
    }
}

double f(double* x, int n) {
    int i; double sum=0;
    for (i = 0; i < n; i++) {
        sum += x[i] * x[i]* x[i];
    }
    return sum;
}

int main() {
    int n; int i;
    scanf_s("%d", &n);
    double* x;
    x = (double*)malloc(n * sizeof(double));
    double* y;
    y = (double*)malloc(n * sizeof(double));
    for (i = 0; i < n; i++)
    {
        printf("x[%d] = ", i);
        scanf_s("%lf", &x[i]);
    }
    grad(y, x, n, 0.001, f);
    printf("grad f(x0,x1,..xn)\n");
    for (i = 0; i < n; i++) {
        printf(" %lf ",y[i]);
    }
   // printf("grad f(1,2) = %lf i + %lf j\n", y[0], y[1]);
}

Ответы (1 шт):

Автор решения: Mikhailo

Вот, смотрите. grad вычисляет градиент - это вектор, который возвращается в массив y. Массив x - точка, в которой считаем градиент. n - размерность вектора. f - функция от n переменных, градиент которой ищем.

include <stdio.h>

void grad(double* y,    // Возвращаемый массив
          double* x,    // Точка, в которой вычисляется градиент
          int n,        // Число переменных
          double d,     // Та самая дельта
          double (*f)(double*, int)) { // Исследуемая функция
    double f0 = f(x, n);
    for (int i = 0; i < n; ++i) {
        double save = x[i];
        x[i] += d;
        double f1 = f(x, n);
        x[i] = save;
        y[i] = (f1 - f0) / d;
        }
    }

double f(double* x, int n) {
    return x[0] * x[0] + x[1] * x[1];
    }

int main() {
    double x[] = {1, 2};
    double y[2];
    grad(y, x, 2, 0.001, f);
    printf("grad f(1,2) = %lf i + %lf j\n", y[0], y[1]);
    }

Далее идет пример - функция от двух переменных f(u,v), которая равна u^2 + v^2. Эти две переменные передаются как массив. И для нее вычисляем градиент в точке (1,2).

По-моему, все должно быть понятно.

Если бы стояла задача для функции от конкретного количества переменных, можно было бы использовать не массивы, а явное f(u,v) например. Но у вас НЕТ функции, для которой мы считаем градиент, а потому пришлось писать обобщенную функцию, чпособную работать с любой функцией от n переменных. Лишь бы массивы были нужного размера.

→ Ссылка