On m'a demandé de calculer l'expression racine imbriquée suivante en utilisant la récursivité uniquement.
J'ai écrit le code ci-dessous qui fonctionne, mais ils nous ont permis d' utiliser une seule fonction et 1 entrée n
à cet effet et non 2 comme je l'ai utilisé. Quelqu'un peut-il m'aider à transformer ce code en une fonction qui calculera l'expression? ne peut pas utiliser n'importe quelle bibliothèque, sauf les fonctions de <math.h>
.
sortie pour 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()
(de<stdlib.h>
), ne retournerais pas silencieusement 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; }
Réponses:
Utilisez les bits supérieurs de
n
comme compteur:Naturellement, cela fonctionne mal lorsque l'initiale
n
estR
ou plus. Voici une version plus compliquée qui fonctionne pour toute valeur positive den
. Ça marche:n
est négatif, cela fonctionne comme la version ci-dessus, en utilisant les bits supérieurs pour compter.n
est positif, s'il est inférieur àR
, il s'appelle avec-n
pour évaluer la fonction comme ci-dessus. Sinon, il s'appelle avecR-1
nié. Cela évalue la fonction comme si elle était appelée avecR-1
. Cela produit le résultat correct car la série cesse de changer au format à virgule flottante après seulement quelques dizaines d'itérations - les racines carrées des nombres plus profonds sont tellement diluées qu'elles n'ont aucun effet. Ainsi, la fonction a la même valeur pour tousn
sur un petit seuil.la source
R
est séparé, donc il peut être réglé. Avant d'n
atteindre 32, la valeur de retour cesse de changer pour IEEE-754 binaire64, et avant d'atteindre 256, la valeur de retour cesse de changer pour des formats raisonnables pourdouble
. J'envisage donc une version alternative qui transforme les entrées de pinces ciR
- dessus , mais elle doit utiliser le bit de signe, et je travaille toujours dessus.n
quelle que soit la largeur deint
.Sans transformer mathématiquement la formule (je ne sais pas si c'est possible), vous ne pouvez pas vraiment utiliser un seul paramètre, car pour chaque élément, vous avez besoin de deux informations: l'étape en cours et l'original
n
. Cependant, vous pouvez tricher . Une façon consiste à coder les deux nombres dans leint
paramètre (comme indiqué par Eric ).Une autre façon consiste à stocker l'original
n
dans une variable locale statique. Au premier appel, nous enregistronsn
dans cette variable statique, nous démarrons la récursivité et à la dernière étape, nous la réinitialisons à la valeur sentinelle:Apparemment, ce
static int n = sentinel
n'est pas du C standard car cesentinel
n'est pas une constante de temps de compilation en C (c'est bizarre parce que gcc et clang ne se plaignent pas, même avec-pedantic
)Vous pouvez le faire à la place:
la source
static int n = sentinel;
ne soit pas entièrement conforme en C car cesentinel
n'est pas une expression constante selon la norme C. Il fonctionne en C ++, et il compile avec les versions actuelles de gcc et clang en mode C mais pas MSVC 2017, mais vous devriez probablement écrirestatic int n = -1;
voir godbolt.org/z/8pEMnzCe problème demande des solutions déformées.
En voici une qui utilise une seule fonction prenant un ou deux
int
arguments:<stdarg.h>
ce qui pourrait ou non être autorisé.Voici le code:
Voici une autre solution avec une seule fonction, utilisant uniquement
<math.h>
, mais abusant des règles d'une manière différente: en utilisant une macro.Encore un autre, à proprement parler récursif , mais avec un seul niveau de récursivité et sans autres astuces. Comme Eric l'a commenté, il utilise une
for
boucle qui pourrait être invalide sous les contraintes de l'OP:la source
double rec_sqrt_series(int n)
, l'OMI atteint les objectifs de l'OP en utilisant le signe comme indicateur de récursivité. (Je laisse tomber leelse
ne pas nécessaire commereturn
est enif
.)else
est possible bien sûr mais j'aime un peu la symétrie des deux branches duif
retour d'un résultat, sorte de style de programmation fonctionnel.Voici une autre approche.
Il repose sur
int
32 bits. L'idée est d'utiliser les 32 bits supérieurs d'un 64 bitsint
pour1) Voir si l'appel était un appel récursif (ou un appel de "l'extérieur")
2) Enregistrez la valeur cible dans les 32 bits supérieurs pendant la récursivité
la source