Есть несколько подходов как решить эту проблему.
Можно передать в функцию solve всегда только функцию принимающую только один параметр x. А если надо передать функцию с большим количеством параметров, то просто создать функцию обёртку с 1 параметром x.
#include <math.h>
#include <iostream>
double q_func(double x, double k, double rhs) {
return x * pow(1 - (k - 1) / (k + 1) * x * x, 1 / (k - 1)) *
pow((k + 1) / 2, 1 / (k - 1)) -
rhs;
}
double solve(double (*f)(double), double x_0 = 2.3, int n = 50) {
double x = x_0;
double dx = 1e-5;
double df = (f(x + dx) - f(x)) / dx;
for (int i = 0; i <= n; i++) {
x_0 = x;
x = x - f(x) / df;
if (x - x_0 < 1e-6) {
return x;
}
}
return x;
}
int main() {
auto wrapper = [](double x) { return q_func(x, 1.4, 0.25); };
double x = solve(wrapper);
std::cout << x << std::endl;
return 0;
}
Можно сделать так чтобы solve принимала любые
Это сработает если k, rhs и остальные параметры известны на этапе компиляции. Если нет то не получится сконвертировать лямбду в указатель на функцию. Можно добавить немного концептов чтобы принимать что угодно вызываемое. Это позволяет передавать лямбды с неизвестными на этапе компиляции параметрами.
#include <math.h>
#include <concepts>
#include <iostream>
double q_func(double x, double k, double rhs) {
return x * pow(1 - (k - 1) / (k + 1) * x * x, 1 / (k - 1)) *
pow((k + 1) / 2, 1 / (k - 1)) -
rhs;
}
template <typename Func>
requires std::invocable<Func, double> &&
std::same_as<double, std::invoke_result_t<Func, double>>
double solve(Func f, double x_0 = 2.3, int n = 50) {
double x = x_0;
double dx = 1e-5;
double df = (f(x + dx) - f(x)) / dx;
for (int i = 0; i <= n; i++) {
x_0 = x;
x = x - f(x) / df;
if (x - x_0 < 1e-6) {
return x;
}
}
return x;
}
int main() {
double k = 1.4;
double rhs = 0.25;
auto wrapper = [=](double x) { return q_func(x, k, rhs); };
double x = solve(wrapper);
std::cout << x << std::endl;
auto wrapper2 =
[](double first, double second) {
return [=](double x) { return q_func(x, first, second); };
};
double x2 = solve(wrapper2(k, rhs));
std::cout << x2 << std::endl;
return 0;
}
Также можно использовать темплейты чтобы передавать любое число параметров в solve и из solve в переданную функцию. Если использовать этот подход параметры для функции должны идти в самом конце что не позволит n и x_0 быть параметрами по умолчанию.
#include <math.h>
#include <iostream>
double q_func(double x, double k, double rhs) {
return x * pow(1 - (k - 1) / (k + 1) * x * x, 1 / (k - 1)) *
pow((k + 1) / 2, 1 / (k - 1)) -
rhs;
}
template <typename... Args>
double solve(double x_0, int n, double (*f)(double, Args...),
Args... args) {
double x = x_0;
double dx = 1e-5;
double df = (f(x + dx, args...) - f(x, args...)) / dx;
for (int i = 0; i <= n; i++) {
x_0 = x;
x = x - f(x, args...) / df;
if (x - x_0 < 1e-6) {
return x;
}
}
return x;
}
int main() {
double k = 1.4;
double rhs = 0.25;
double x = solve(2.3, 50, q_func, k, rhs);
std:: cout << x << std::endl;
return 0;
}