Funções recursivas e saída de código estranha

28 respostas
danielbussade

Olá a todos, alguém poderia me explicar a saída do código abaixo:

public class Main {
    public static int x(int n) {
        if (n>2)
          return 3+x(n-1);
        else
          return 0;
    }
    public static void main(String[] args) {
        int x,y,z;
        x=0;
        y=0;
        z=10;
        for (int i=0;i<120;i++)
            x+=1;
        for (int j=1;j<=5;j+=2)
            y+=2;
        int a=x(6);
        z=x+y+x(6);
        System.out.println(z);
    }
}

Eu achei que seria 126, mas a resposta é 138.

Obrigado

28 Respostas

evandro.santos

Coloca outros System.out no código e você poderá acompanhar passo a passo…

E

Isso é da prova de analista do Banco Central. Que tal usar o depurador de sua preferência (Netbeans ou Eclipse) e acompanhar passo a passo os valores das variáveis?

danielbussade

Obrigado. Mas eu já entendi, eu não tinha entendido que o último return e o return da chamada recursiva e não da primeira chamada.

E

Queria saber se você foi bem nessa prova (o gabarito saiu ontem mesmo). Quantas questões você acertou?

sergiotaborda

danielbussade:
Olá a todos, alguém poderia me explicar a saída do código abaixo:

public class Main {
    public static int x(int n) {
        if (n>2)
          return 3+x(n-1);
        else
          return 0;
    }
    public static void main(String[] args) {
        int x,y,z;
        x=0;
        y=0;
        z=10;
        for (int i=0;i<120;i++)
            x+=1;
        for (int j=1;j<=5;j+=2)
            y+=2;
        int a=x(6);
        z=x+y+x(6);
        System.out.println(z);
    }
}

Eu achei que seria 126, mas a resposta é 138.

Primeiro for, some 1 em x para todos os valores de 0 a 119. x = 120
Segundo for, some 2 em y para todos os impares de 1 a 5 . y = 6 (existem 3 impares, 3*2 =6)

Terceiro, somes 120 com 6 e o resultado do metodo x aplicado a 6 ( que dá 12)

z= 120 + 6 + 12 = 138 cqd

P.S. O objetivo destes exercicios é ver se vc entende codigo. Correr o codigo vai lhe dar o resultado, mas não vai explicar por quê.

E

Isso não era exatamente um “exercício”. Vale um salário de R$ 13.000,00 no Banco Central :slight_smile:
De qualquer maneira, há uma maneira relativamente simples de rodar uma rotina recursiva “no braço”. Basta você criar um tipo de planilha com os valores:

x(0) = 0
x(1) = 0
x(2) = 0
x(3) = 3 + x(2) = 3 + 0 = 3
x(4) = 3 + x(3) = 3 + 3 = 6

e assim por diante.

evertonsilvagomesjav

como que funciona essa chamada?

pq ele testa no if(n>2), e retorna true pq o n é 6, ele retorna 3+x(n-1) aqui ele chama o método de novo passando 5? passa e chama o metodo passando 4? é isso?

sergiotaborda

entanglement:
Isso não era exatamente um “exercício”. Vale um salário de R$ 13.000,00 no Banco Central :slight_smile:

O que eu quiz dizer é que para saber resolver tem que fazer na mão já que na prova não pode rodar um debugger.
Aliás, se precisa de um debugger pare entender o codigo é melhor mudar de profissão. :slight_smile:

É um exercicio muito simples para esse valor de salário… :roll:

E

evertonsilvagomesjava:
como que funciona essa chamada?

pq ele testa no if(n>2), e retorna true pq o n é 6, ele retorna 3+x(n-1) aqui ele chama o método de novo passando 5? passa e chama o metodo passando 4? é isso?

@Everton: Não queria dizer isso, já que vale R$ 13.000,00 por mês e eu acho que quem quer ganhar R$ 13.000,00 sendo analista de TI teria de saber isso, mas basicamente é isso mesmo.

Seu professor não ensinou como calcular o fatorial de maneira recursiva, ou você faltou a essa aula?

@Daniel: Acho que embora a questão tenha sido formulada com base em um programa que é legal* em Java, ela pode ser contestada, já que o uso de “x” como nome de função e nome de variável em um mesmo contexto, significando coisas diferentes em uma mesma expressão, só existe em Java (não existe em C#, por exemplo, ou em C++), e pode levar a confusão, conforme você mesmo percebeu. Portanto, talvez essa questão possa até ser anulada, por ser maliciosa (“pegadinha”).

  • Legal no sentido de “de acordo com a Java Language Specification”. Faça isso (declarar uma variável e um método com o mesmo nome, e misturar os dois em uma mesma expressão) em uma prova de emprego e o seu examinador vai lhe tirar pontos, já que isso leva a código confuso e sujeito a erros.
sergiotaborda

bom, teria que ver o enunciado, mas se o enunciado tem algo do tipo “considere este codigo em Java. O que é impresso na tela” está mais que válido. Se o cada não sabe java, o problema é dele. Veja que a escolha de java pode não ser aleatória (que o a politica do governo se move para software aberto e a maioria é em java). Claro que poderiamos ter a mesma pergunta em pseudo-codigo ou em ruby. O uso de sombreamento não é pegadinha é algo que se espera que um programdor java conheça. A pergunta sim é especifica em java, mas sem conhecer o edital ou o enunciado, não me parece que só isso a classifique para anulamento.

E

Prova Analista TI Banco Central

É a questão 28.

V

aproveitando o tópico, onde encontrar informações referentes a estes concursos relacionados a área da informática???..

boa sorte no resultado da prova danielbussade :slight_smile:

evertonsilvagomesjav

entaglement nunca tive aula, vou começar faculdade agora em fevereiro, se vc nao quiser explicar sinta-se a vontade nao posso forçar ninguem a me explicar, de fato eu nao entendi como que seria o retorno ali, se ele so vai retornar quando sair do método recursivo ou algo assim…

danielbussade

Olá, na verdade eu não fiz a prova. Só dei uma olhada para ver as questões da mesma.

Valeu

danielbussade

Na verdade, a questão é realmente simples, o meu erro foi não perceber que o último retorno era das chamadas recursivas e não da primeira chamada, por isso ele não sai do método, o resto é bem simples de entender.

Obrigado a todos.

E

Ah, certo, não sabia disso.

Acho que é melhor começar do começo.

Um método recursivo é aquele que pode se chamar a si mesmo. Simples, não?

Para você não se embananar, não fique pensando em “chamadas” e “retornos” por enquanto. Vou explicar como eu gostaria de ter aprendido.

A recursividade é a arte de resolver problemas grandes, quando você:

  • Sabe resolver um problema menor;
  • E o problema maior pode ser resolvido se você souber resolver o problema menor.

Por exemplo, você pode construir uma casa (problema maior) se você souber construir uma parede (problema menor), e você pode construir uma parede (problema maior) se você souber empilhar tijolos (problema menor).
Para construir uma parede com altura de 10 tijolos (problema maior), se você souber como construir uma parede com altura de 9 tijolos, então é só empilhar mais uma fieira de tijolos nessa parede.

Ou seja:

parede (altura de 0 tijolos) =  // problema menor
    nada
parede (altura de 1 tijolo) = // problema menor
    empilhar 1 fieira de tijolos
parede (altura de N tijolos) = // problema maior
    parede (altura de N - 1 tijolos) +
    empilhar 1 fieira de tijolos
evertonsilvagomesjav

quanto a retornos de métodos e chamadas eu entendo bem sim, o que é método recursivo eu tb sei, quero entender o processo dele ali pra chegar no resultado que da 12, so isso que ta pegando o resto eu entendo perfeitamente.

E

x(0) = 0
x(1) = 0
x(2) = 0
x(3) = 3 + x(2) = 3 + 0 = 3
x(4) = 3 + x(3) = 3 + 3 = 6
x(5) = 3 + x(4) = 3 + 6 = 9
x(6) = 3 + x(5) = 3 + 9 = 12

Ou seja, x(6) = 12. Você não tinha entendido a lógica?

evertonsilvagomesjav

to entendendo dessa forma:

onde que é somado o 3? Isso que nao to enchergando pq pra mim ele iria fazendo recursão ate retornar 0.

Nykolas_Lima

evertonsilvagomesjava:
to entendendo dessa forma:

onde que é somado o 3? Isso que nao to enchergando pq pra mim ele iria fazendo recursão ate retornar 0.

A função retorna um INT.

Sendo return 3+x(6-1);

Vai retornar 3 + o resultado da chamada x(6-1);

Você não teve lógica na facu/colégio?

evertonsilvagomesjav

A função retorna um INT.

Sendo return 3+x(6-1);

Vai retornar 3 + o resultado da chamada x(6-1);

Você não teve lógica na facu/colégio?

LOL cara deixa pra la.

E

Everton, você viu que eu nem tentei começar a calcular o valor de x(6) diretamente, porque quando se trata de funções recursivas você tem de pensar ao contrário - você tem de pensar com os valores menores, onde a solução é mais simples, e depois partir para os valores maiores, que dependem dos valores menores.

Você tentou começar a calcular x(6) diretamente, e aí é que seu cérebro deu um nó. Nem eu tento fazer isso, porque dá um “stack overflow” na cabeça.

Eu calculei x(0), x(1) … até chegar a x(6).

O grande problema é que se você aprendeu a programar sozinho, é bem difícil pensar ao contrário.

Se você tiver um professor talvez também não aprenda direito isso (que em funções recursivas você tem de pensar ao contrário).
É que eles também não entenderam isso direito.
E foi por isso que eu mostrei como eu gostaria de ter aprendido.

evertonsilvagomesjav

Entanglement a lógica que vc passou eu comecei a entender ela, pq eu debuguei aqui no eclipse e quando ele retorna 0 ou seja quando ele entra no "else", ele volta ai return do "if".

olha só, vou tentar expor do jeito mais grosso possivel pra ver se vc consegue me ajudar.
public static int x(int n) {   
	  
if (n > 2){
return 3+x(6-1);   // 3 + o que? se ta chamando o método novamente?  5 é maior que 2? true! vai cair no return 3+x(5-1) o que aqui ele vai somar com 3 se ta chamando de novo o método? Então cairia no 3+ x(4-1), ai ele cairia 3+(3-1) e retornaria 0 e sairia do método.
 }else   
return 0;   
 }

Enfim a recursão eu entendi nao entendo como ta somando o 3 se toda hora ele ta chamando o método pra fazer recursão. Se nao consigui me expor da melhor forma não esquentem nao rsrs.

E

Para entender esse método, é melhor usar uma notação mais “matemática”.

Espero que você não tenha alergia de matemática, como muita gente boa que eu conheço tem.

Nesse caso, seria assim:

x (n) = 0                 se n <= 2.
x (n) = 3 + x (n - 1) se n > 2.

Aí você pega uma planilha Excel, e joga os dados lá, a partir de n = 0.

n = 0 -> x (n) = 0 porque 0 <= 2 .
n = 1 -> x (n) = 0 porque 1 <= 2.
e assim por diante. Não vou repetir tudo de novo.

Eu simplesmente nem tento ficar vendo essa parte do “fulano que chamou sicrano que chamou beltrano e que retornou blablebli” - isso é fatal para dar um nó na sua cabeça. Nem os matemáticos fazem isso.

Abdon

Esta prova esta disponivel na net para qualquer um baixar?

Alguem sabe me indicar onde?

evertonsilvagomesjav

Nossa entenglament até que fim encherguei rsrs, cara mto obrigado pelas explicações e desculpa qualquer coisa.

E

ovelha:
Esta prova esta disponivel na net para qualquer um baixar?

Alguem sabe me indicar onde?

http://www.guj.com.br/posts/list/197092.java#988733

Abdon

:oops: :oops:

Criado 2 de fevereiro de 2010
Ultima resposta 3 de fev. de 2010
Respostas 28
Participantes 8