Pediram-me para calcular a seguinte expressão raiz aninhada usando apenas recursão .
Eu escrevi o código abaixo que funciona, mas eles nos permitiram usar apenas uma função e 1 entrada n
para esse fim, e não 2 como eu usei. Alguém pode me ajudar a transformar esse código em uma função que calculará a expressão? não pode usar nenhuma biblioteca, exceto as funções de <math.h>
.
saída 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()
(de<stdlib.h>
), e não retornaria 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; }
Respostas:
Use os bits superiores de
n
como um contador:Naturalmente, isso funciona mal quando a inicial
n
éR
ou maior. Aqui está uma versão mais complicada que funciona com qualquer valor positivo den
. Funciona:n
é negativo, funciona como a versão acima, usando os bits superiores para contar.n
é positivo, se for menor queR
, chama-se-n
para avaliar a função como acima. Caso contrário, ele se chamaR-1
negado. Isso avalia a função como se fosse chamada comR-1
. Isso produz o resultado correto porque a série para de mudar no formato de ponto flutuante após apenas algumas dezenas de iterações - as raízes quadradas dos números mais profundos ficam tão diluídas que não têm efeito. Portanto, a função tem o mesmo valor para todon
um pequeno limite.fonte
R
é separado, para que possa ser ajustado. Antes den
atingir 32, o valor de retorno para de mudar para IEEE-754 binary64 e, antes de atingir 256, o valor de retorno para de mudar para formatos razoáveisdouble
. Por isso, estou considerando uma versão alternativa que transforma as entradas dos grampos acimaR
, mas ele precisa usar o bit de sinal e ainda estou trabalhando nisso.n
independentemente da largura deint
.Sem transformar matematicamente a fórmula (não sei se é possível), você não pode realmente usar apenas um parâmetro, pois para cada elemento você precisa de duas informações: a etapa atual e a original
n
. No entanto, você pode trapacear . Uma maneira é codificar os dois números noint
parâmetro (como mostrado por Eric ).Outra maneira é armazenar o original
n
em uma variável local estática. Na primeira chamada que salvamosn
nessa variável estática, iniciamos a recursão e, na última etapa, redefinimos para o valor sentinela:Aparentemente, o
static int n = sentinel
C não é padrão porquesentinel
não é uma constante de tempo de compilação em C (é estranho porque o gcc e o clang não reclamam, mesmo com-pedantic
)Você pode fazer isso:
fonte
static int n = sentinel;
não seja totalmente compatível com C porquesentinel
não é uma expressão constante conforme o Padrão C. Funciona em C ++ e é compilado com as versões atuais de gcc e clang no modo C, mas não no MSVC 2017, mas você provavelmente deve escrever emstatic int n = -1;
see godbolt.org/z/8pEMnzEsse problema implora por soluções distorcidas.
Aqui está um que usa uma única função usando um ou dois
int
argumentos:<stdarg.h>
quais podem ou não ser permitidos.Aqui está o código:
Aqui está outra solução com uma única função, usando apenas
<math.h>
, mas abusando das regras de uma maneira diferente: usando uma macro.Outro, estritamente falando recursivo , mas com um nível de recursão único e sem outros truques. Como Eric comentou, ele usa um
for
loop que pode ser inválido sob as restrições do OP:fonte
double rec_sqrt_series(int n)
, a IMO atende aos objetivos do OP usando o sinal como sinalizador de recursão. (Eu deixaria cair oelse
que não é necessário comoreturn
está emif
.)else
é claro que é possível largar o arquivo, mas eu meio que gosto da simetria de ambos os ramos doif
retorno de um resultado, tipo de estilo de programação funcional.Aqui está outra abordagem.
Depende de
int
ter 32 bits. A idéia é usar os 32 bits superiores de 64 bitsint
para1) Veja se a chamada foi recursiva (ou uma chamada de "fora")
2) Salve o valor alvo nos 32 bits superiores durante a recursão
fonte