Как выполнить моделирование вложенной функции в ANSI C, где я могу динамически обновлять свои функции? пожалуйста, посмотрите на все объяснение

Я новичок в этом сообществе, и я хотел бы задать один вопрос. Я не программист / разработчик, но я использую программирование для ускорения своих научных вычислений. Раньше я много использовал Python, но теперь, из-за моей новой работы, мне нужно использовать язык программирования Си. Я новичок, и это довольно сложно, но я борюсь:D. Мой главный вопрос заключается в том, как выполнить такой код от Python до C:

def foo(x,a):
    def en(x):
        return a*x
    return en

Я использую это, чтобы получить динамически окончательные уравнения, и я могу написать свои решатели для множества различных примеров. По сути, я хочу сделать то же самое в C. Поскольку ansi C не поддерживает вложенные функции, я не могу получить это с помощью typdefs или просто не могу понять, как это сделать. Я много искал ответа, но не нашел его.

Заранее спасибо. PS извините за мой плохой английский если он есть: D

РЕДАКТИРОВАТЬ: я забыл добавить свой пример кода, откуда я пытался сделать то же самое: D, но я получил ошибку, потому что ANSI C не поддерживает вложенные функции

double fun(double x, double a){
return a*x-5;
}
double n(double x);
typedef double (*function)(double);
function wrapper(double x, double a){
    function ptr;
    double functionReturn(double x){
        return fun(a,x);
    }
    ptr = functionReturn;
    return ptr;
}

1 ответ

Как уже упоминалось, вы не можете создавать функции на лету в C. Поэтому ваш подход должен быть совершенно другим, и то, как вы его адаптируете, будет зависеть от деталей того, что вы пытаетесь выполнить. Я покажу два способа заменить функцию, возвращающую поведение функции.

Подход 1: Если вам нужно использовать только 1 возвращаемую функцию за раз.

Как правило, если вы вычисляете функции на лету, функции, возвращаемые данной функцией, будут очень похожи друг на друга. Вы можете использовать статическое хранилище данных, чтобы получить этот эффект, предполагая, что вам нужна только одна действительная возвращаемая функция за раз.

static double fun_a;

double fun( double x )
{
   return fun_a*x - 5;
}

void wrapper( double a )
{
   fun_a = a;
}

В вашем примере у вас есть функция с двумя аргументами 'fun', и вы хотите функцию, которая возвращает функции, которые передаются с помощью фрагмента fun, заданного путем фиксации одного аргумента. Когда вы вызываете "обертку (a)", "fun" по существу изменяется таким образом, что вызов "fun(x)" аналогичен вызову "fun(x,a)" (связывание второго аргумента "a" со статической переменной ". fun_a').

По сути, вместо того, чтобы возвращать функцию, "обертка" изменяет существующую функцию на ту, которую она возвратила бы (и фактически ничего не возвращает). Таким образом, вы получаете тот же эффект, вы можете использовать только один возврат за раз.

Если вы подумаете о ситуациях, в которых вы хотите вычислить функцию, вы, вероятно, увидите, что почти всегда довольно просто определить функцию, которая использует глобальные переменные, и получить желаемую функцию, изменив эти глобальные переменные.

Обратите внимание, что глобальные переменные доступны из других частей программы, будьте осторожны с тем, как вы их называете, чтобы избежать их путаницы в другом месте. Если у меня есть функция 'fun' и я определяю что-то глобальное, чтобы согласиться с ней, я обычно называю это 'fun_[что-то]', чтобы таких проблем было легко избежать.

Наконец, если у вас есть какое-то небольшое фиксированное ограничение на количество функций, которые вам нужно использовать одновременно, вы можете достичь своей цели, выполнив что-то вроде этого:

static double fun1_a;

double fun1( double x )
{
   return a*x - 5;
}

void wrapper1( double a )
{
   fun1_a = a;
}



static double fun2_a;

double fun2( double x )
{
   return a*x - 5;
}

void wrapper2( double a )
{
   fun2_a = a;
}

.
.
.

Подход 2: Используйте typedef

Пример, который вы привели, очень прост, я полагаю, потому что ваша ситуация слишком сложна, чтобы задавать этот вопрос в реальном контексте. Этот второй подход требует немного более сложного примера, чтобы иметь смысл.

Скажем, у вас есть функция E(x,m), которая вычисляет, сколько общих факторов x и m имеют общее. Это потенциально очень дорогая функция, поэтому вам может потребоваться вычислить функцию F_k(m), которая вычисляет, сколько общих простых факторов k и m имеет общее, так как это было бы значительно более быстрой функцией. Обратите внимание, что E принимает переменную x, тогда как k фиксировано для F_k, поэтому функции выполняют разные роли.

Это просто произвольный пример, демонстрирующий технику для выполнения подобных действий в более сложной ситуации, чем просто взятие части функции более высокой арности.

Вы можете сделать что-то вроде:

typedef long long unsigned llu;
typedef llu* F_type;

int fun( F_type L, llu m )
{
   int i, j=0;
   for(i=0; L[i]; ++i)
      if( m % L[i] == 0 ) ++j;
   return j;
}

F_type wrapper( llu k )
{
   // code that returns an array listing the primes dividing k, followed by 0
}

Таким образом, вместо вызова какой-либо функции, которая возвращает F_k для данного k, вы можете просто вызвать wrapper(k), установить результат в L и вызвать fun(L,m). Тогда L выполняет роль функции F_k, по существу, превращая fun в F_k.

Преимущество этого подхода заключается в том, что любое количество таких типов может быть активным в программе в данный момент.

Реальный ответ на ваш вопрос заключается в том, что вам просто нужно реструктурировать свой подход, чтобы использовать типы данных, которые могут быть созданы во время выполнения. Я надеюсь, что эти два примера помогут проиллюстрировать некоторые способы сделать это в C.

Другие вопросы по тегам