Me pidieron que calcule la siguiente expresión de raíz anidada usando solo recursión .
Escribí el siguiente código que funciona, pero nos permitieron usar solo una función y 1 entrada npara el propósito y no 2 como usé. ¿Alguien puede ayudarme a transformar este código en una función que calcule la expresión? No puedo usar ninguna biblioteca excepto las funciones de <math.h>.
salida para n = 10: 1.757932
double rec_sqrt_series(int n, int m) {
if (n <= 0)
return 0;
if (m > n)
return 0;
return sqrt(m + rec_sqrt_series(n, m + 1));
}
double helper(int n) {
return rec_sqrt_series(n, 1);
}


helper?abort()(desde<stdlib.h>), no devolvería silenciosamente 0.double nested_root(unsigned n) { double x = 0.0; if (n > 0) { x = nested_root(0); for (unsigned i = n; i > 0; i--) { x = sqrt(i + x); } } return x; }Respuestas:
Use los bits superiores de
ncomo contador:Naturalmente, eso funciona mal cuando la inicial
nesRo mayor. Aquí hay una versión más complicada que funciona para cualquier valor positivo den. Funciona:nes negativo, funciona como la versión anterior, utilizando los bits superiores para contar.nes positivo, si es menor queR, se llama a sí mismo-npara evaluar la función como se indicó anteriormente. De lo contrario, se llama a sí mismo conR-1negado. Esto evalúa la función como si se llamara conR-1. Esto produce el resultado correcto porque la serie deja de cambiar en el formato de punto flotante después de unas pocas docenas de iteraciones: las raíces cuadradas de los números más profundos se diluyen tanto que no tienen ningún efecto. Por lo tanto, la función tiene el mismo valor para todosnen un umbral pequeño.fuente
Restá separado, por lo que se puede ajustar. Antes denllegar a 32, el valor de retorno deja de cambiar para IEEE-754 binary64, y antes de llegar a 256, el valor de retorno deja de cambiar para formatos razonables paradouble. Así que estoy considerando una versión alternativa que transforma las entradas de las abrazaderas anterioresR, pero necesita usar el bit de signo, y todavía estoy trabajando en ello.nindependientemente del ancho deint.Sin transformar matemáticamente la fórmula (no sé si es posible), no puede usar realmente un solo parámetro, ya que para cada elemento necesita dos informaciones: el paso actual y el original
n. Sin embargo, puedes hacer trampa . Una forma es codificar los dos números en elintparámetro (como lo muestra Eric ).Otra forma es almacenar el original
nen una variable local estática. En la primera llamada que guardamosnen esta variable estática, comenzamos la recursión y en el último paso la restablecemos al valor centinela:Aparentemente
static int n = sentinelno es C estándar porquesentinelno es una constante de tiempo de compilación en C (es extraño porque tanto gcc como clang no se quejan, incluso con-pedantic)Puedes hacer esto en su lugar:
fuente
static int n = sentinel;no es totalmente conforme en C porquesentinelno es una expresión constante según el Estándar C. Funciona en C ++, y se compila con las versiones actuales de gcc y clang en modo C, pero no en MSVC 2017, pero probablemente debería escribirstatic int n = -1;vea godbolt.org/z/8pEMnzEste problema pide soluciones retorcidas.
Aquí hay uno que usa una sola función tomando uno o dos
intargumentos:<stdarg.h>que podría o no estar permitido.Aquí está el código:
Aquí hay otra solución con una sola función, usando solo
<math.h>, pero abusando de las reglas de una manera diferente: usando una macro.Otro más, estrictamente hablando recursivo , pero con un solo nivel de recursión y sin otros trucos. Como Eric comentó, usa un
forbucle que podría ser inválido bajo las restricciones del OP:fuente
double rec_sqrt_series(int n), IMO cumple con los objetivos de OP utilizando el signo como una bandera de recursión. (elsereturnifelsedescartar es posible, por supuesto, pero me gusta un poco la simetría de ambas ramas de laifdevolución de un resultado, una especie de estilo de programación funcional.Aquí hay otro enfoque.
Se basa en
intser de 32 bits. La idea es utilizar los 32 bits superiores de 64 bitsintpara1) Vea si la llamada fue recursiva (o una llamada desde el "exterior")
2) Guarde el valor objetivo en los 32 bits superiores durante la recursividad
fuente