Duda Recursividad

Vikkktor

Hola, tengo aquí el programa de un compañero de clase, el programa pide un número en decimal y te lo muestra en binario, y se tiene que hacer obligatoriamente utilizando un método recursivo.

Pero por más que miro el código, no lo entiendo...

{
    class Recursividad01
    {
        static void Main(string[] args)
        {
            Recursividad01 ObjRecursivo = new Recursividad01();
            try
            {

            int numero;

            // Introducimos el numero en decimal.
            Console.Write("Introduce un numero decimal positivo:  ");
            numero = Convert.ToInt32(Console.ReadLine());

            // Comprobamos que sea positivo.
            if (numero < 0) Console.Write("ERROR.   El numero debe ser positivo \n");
            else
            {
            // Lo enviamos al metodo Abinario para que lo calcule.
             ObjRecursivo.Abinario(numero);

             // Añadimos linea en blanco despues de presentar los numeros.
             Console.WriteLine("");
            }
        }
        catch (Exception texto)
        {
            Console.Write("ERROR.  {0}", texto);
        }
    }
    public void Abinario(int numero)
    {
        int cociente, resto;
        cociente = numero / 2;
        resto = numero % 2;
        if (cociente != 0) // Si no finalizamos la division lo enviamos al metodo de nuevo.
        {
            Abinario(cociente);
        }
        Console.Write(resto);
    }
}
}

A ver, el método principal pide el número en decimal, y lo envía al método Abinario,
este lo divide entre dos, calcula el resto de la división, y si el cociente no es cero, vuelve a llamar al método y le entrega el número dividido.

Hasta ahí bien, pero me surge la duda cuando el cociente se hace cero, y el programa escribe el "resto".

No se supone que cada vez que el bucle empieza, el valor del resto toma un nuevo valor? el que haya dejado la división en ese momento?

Por ejemplo, metemos el número 2.

2/2; cociente= 1, resto = 0,
cociente es distinto de 0, así que volvemos a hacer el método.

1/2; cociente= 0, resto =1,
cociente es 0, así que ya no vuelve a llamarse el método, y se escribe el resto, que en este momento es 1.

Así es como yo entiendo el proceso, pero el programa me devuelve un "10", es decir, coje el último resto y me lo muestra junto con el que había cogido anteriormente, pero no soy capaz de ver como hace eso..

A ver si alguien tiene moral y ganas para explicarlo :f5:

Un saludo.

eXtreM3

La parte de

Console.Write(resto);

está fuera del if del cociente, por lo que lo escribirá siempre, por eso te muestra todos los restos...

Vikkktor

mmm vale eso si,
pero por qué los escribe en orden inverso?
es decir,
2/2, resto=0,
1/2, resto=1,

escritos según el orden en el que los va haciendo, debería devolver "01", en vez de "10".

Y por qué los devuelve todos de golpe cuando se acaba el bucle?, si siempre los escribe debería ir mostrando los restos de cada operación.

1 respuesta
cabron

#3

Llamar a una función de forma recursiva tiene el mismo efecto que llamar a una función normal, la ejecución se para en la función llamante, y cuando la función llamada termina, se continúa la función llamante desde el punto en el que se quedó, por eso los devuelve de golpe

2 1 respuesta
Vikkktor

#4 muchas gracias por la currada,
entonces se puede ver como que lo que debería hacer el método cada vez que lo llaman, se hace pero no se muestra, y cuando el bucle termina y al método ya no se le llama más, va desde dónde terminó, hacia el principio haciendo lo que debió haber hecho en cada llamada?

1 respuesta
cabron

#5

Eso que pones me parece una forma muy rebuscada. Como te dije en el otro post, lo que tienes que hacer es ver la llamada recursiva como una llamada normal a una función.

Piensa en una función que lo único que hace es llamarse así misma:


miFuncion(){

   miFuncion()

}

El resultado es que la función se llama a sí misma de forma infinita (bueno realmente peta cuando se desborde la pila):

Está claro que cuando usas recursividad, en algún momento tienes que hacer que la función deje de llamarse a sí misma, esto se consigue metiendo la llamada dentro de un if. En el siguiente ejemplo, se coge un número, y se le resta 1. Si el resultado es mayor que 0, se vuelve a llamar a al función:


miFuncion(int n)
{    
if(--n > 0) miFuncion(n) }

Aquí viene lo importante, como esto no son más que llamadas a funciones, cuando termina la última llamada, devuelve el control a la llamada anterior, que a su vez devuelve el control a la anterior, y así hasta llegar a la primera llamada.

Eso significa que si pones código entre el if donde se hace la llamada recursiva y el retorno de la función, ese bloque se ejecutará de forma inversa, primero en la última llamada, luego en la penúltima, luego en la antepenúltima, etc.

En este ejemplo se imprime el valor de n:


miFuncion(int n)
{    
if(--n > 0) miFuncion(n) print(n) }

El resultado de print (5 ) es :

0
1
2
3
4

10 4 respuestas
Li3cht

#6

Vikkktor

captado!
joder, menuda explicación que te has marcado, muchisimas gracias, si no tienes curro vente a mi instituto que nos deshacemos de nuestro cabrón de programación en un momento! haha

PD: espero que no sea MediaVidero..

Kartalon

#6 ¿Los diagramas con Visual Paradigm?

2 respuestas
Shaktale

#6 Ojo a la currada +100000

Lecherito

#9 Sip, lo son.

#12 Yo tengo una versión de estudiante, xD Si alguno la quiere probar que me avise.

cabron

#9

Sí, me lo compré hace un par de años cuando la empresa en la que estaba solo me daba una versión antigua del Rational Rose que era una jodida porquería, que vamos no sé como serán las versiones recientes, pero aquella era infumable.

1 2 respuestas
Maaarc

#12 Eres un crack tío. CLAP.

eXtreM3

#6 this is mv, lugar donde la gente se pega un currazo desinteresadamente y queda como Dios.

Usuarios habituales

  • eXtreM3
  • Maaarc
  • cabron
  • Lecherito
  • Shaktale
  • Kartalon
  • Vikkktor