¿Cómo se puede declarar una función en C ++ para hacer un programa de bisección que encuentre la raíz de alguna función f (x)?

Para promover lenguajes funcionales, muestro una función para encontrar una raíz para alguna función [math] f (x) [/ math] usando el método de bisección. El intervalo es [math] [x, y] [/ math], donde [math] \ operatorname {sgn} (f (x)) \ not = \ operatorname {sgn} (f (y)) [/ math] es condición previa. La precisión es [matemáticas] eps [/ matemáticas]. El idioma es Haskell.

bisección :: (Núm. a, Eq a, Fraccional a, Ord a) => (a-> a) -> a-> a-> a-> a
bisect fxy eps | fx == fromIntegral 0 = x
El | fy == fromIntegral 0 = y
El | sx == sy = error “mismo signo de f (x) yf (y)”
El | abs (xy) <= eps = x
El | sx / = sm = bisecto fxm eps
El | de lo contrario = bisecar fmy eps
dónde
s = signum. F
m = (x + y) / 2

En el mismo espíritu, una posible implementación de C ++ (aún no completamente probada), aplicada a la función [matemática] f (x): = x ^ 2–2 [/ matemática] y buscando una raíz entre [matemática] x = 0 [/ math] y [math] y = 3 [/ math]:

#include
#incluye
#include
#include
#include

plantilla
int signum (T x) {
retorno (T (0) <x) – (x <T (0));
}

doble bisección (std :: function f,
doble x, doble y, doble eps) {
auto s = [& f] (doble z) -> doble {signo de retorno (f (z));};

if (f (x) == 0) {return x;}
if (f (y) == 0) {return y;}
if (s (x) == s (y)) {
throw std :: invalid_argument (“x e y tienen el mismo signo”);
}
más si (eps <= 0) {
throw std :: invalid_argument (“eps no positivo”);
}
// sabemos que los signos de f (x) yf (y) son opuestos, entonces una raíz
// se encuentra en el intervalo [x, y]. Su diferencia es
// eps menos o igual. Entonces encontramos una raíz.
if (std :: abs (xy) <= eps) {return x;}

doble m = (x + y) / 2;
if (s (x)! = s (m)) {
bisecto de retorno (f, x, m, eps);
}más{
bisecto de retorno (f, m, y, eps);
}
}

int main () {
diversión automática = [] (doble x) -> doble {return std :: pow (x, 2) -2;};
double xroot = bisect (diversión, 0, 3, 1e-15);
std :: cout << std :: setprecision (16) << "raíz:" << xroot << std :: endl;
}

Salida de la aplicación:

raíz: 1.414213562373095

Método de bisección – Wikipedia

std :: vector bisect_function_roots (
const std :: mapa <
doble / * potencia de x * /,
doble / * coeficiente * /> & f);

Puede usar flotante o doble según su precisión. Si la precisión esperada es mayor, es mejor usar el doble como tipo de retorno.