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

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

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

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?

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.

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

[quote=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.
[/quote]

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ê.

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.

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?

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

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:

[quote=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?[/quote]

@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.

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.

Prova Analista TI Banco Central

É a questão 28.

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:

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…

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

Valeu

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.

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

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.

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?

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.