NUMERON.c



// OPERACIONES CON NUMEROS DE VARIOS DIGITOS

#include <stdio.h>
#include <stdlib.h>

struct numero
{
   int num;
   struct numero *ant;
   struct numero *sig;
};


int longitud(struct numero *a)
{
   int x = 0;

   while (a)
   {
      x++;
      a = a->sig;
   }
   return x;
}

struct numero *crea_espacio(void)
{
   struct numero *nodo;

   if (!(nodo = (struct numero *) malloc(sizeof(struct numero))))
      { puts("no hay memoria...\n"); return NULL; }
   nodo->sig = NULL;
   nodo->ant = NULL;
   return nodo;
}

struct numero *inv(struct numero *x)
{
   struct numero *nodo = NULL;
   struct numero *ant  = NULL;

   while(x)
   {
      nodo = crea_espacio();
      nodo->num = x->num;
      if (!ant) {ant = nodo;}
      else
      { ant->ant = nodo; nodo->sig = ant; ant = nodo;}
      x = x->sig;
   }
   return ant;
}

struct numero *pide_numero(void)
{
   int valor = 0;
   struct numero *nodo    = NULL;
   struct numero *primero = NULL;
   struct numero *ant     = NULL;

   puts("\ntermine con un -1\n");
   while(valor >= 0)
   {
      scanf("%d", &valor);
      if (valor < 0) continue;
      nodo = crea_espacio();
      nodo->num = valor;
      if (!ant) {ant = nodo; primero = nodo; }
      else
      { ant->sig = nodo; nodo->ant = ant; ant = nodo; }
   }
   return primero;
}


void imprime(struct numero *valor)
{
   puts("respuesta: \n");
   while(valor)
   {
      printf("%d", valor->num);
      valor = valor->sig;
   }
   puts("\n");
}

struct numero *suma(struct numero *a, struct numero *b)
{
   struct numero *x       = NULL;
   struct numero *y       = NULL;
   struct numero *salida  = NULL;
   struct numero *nodo    = NULL;
   struct numero *ant     = NULL;
   int valor, long_a, long_b, acarreo = 0;
   div_t checa;

   if (!a && !b) return NULL;
   if (!a) return b;
   if (!b) return a;

   long_a = longitud(a);
   long_b = longitud(b);

   if (long_a > long_b)  {x = inv(a); y = inv(b);}
   if (long_a < long_b)  {x = inv(b); y = inv(a);}
   if (long_a == long_b) {x = inv(a); y = inv(b);}

   while(x)
   {
      if (!y) valor = 0;
      else    valor = y->num;

      valor = x->num + valor + acarreo;
      checa = div(valor, 10);
      if (checa.rem >= 1)
      {
         acarreo = checa.quot;
         valor   = checa.rem;
      }
      else acarreo = 0;

      nodo = crea_espacio(); 
      nodo->num = valor; 
      if (!ant) {ant = nodo; salida = nodo; }
      else
      { ant->sig = nodo; nodo->ant = ant; ant = nodo;}

      x = x->sig;
      if (y) y = y->sig;
   }
   return inv(salida);
}

struct numero *resta(struct numero *a, struct numero *b)
{
   struct numero *x       = NULL;
   struct numero *y       = NULL;
   struct numero *salida  = NULL;
   struct numero *nodo    = NULL;
   struct numero *ant     = NULL;
   int valor, long_a, long_b, acarreo = 0;
   int checa;

   if (!a && !b) return NULL;
   if (!a) return b;
   if (!b) return a;

   long_a = longitud(a);
   long_b = longitud(b);

   if (long_a > long_b)  {x = inv(a); y = inv(b);}
   if (long_a < long_b)  {x = inv(b); y = inv(a);}
   if (long_a == long_b) {x = inv(a); y = inv(b);}

   while(x)
   {
      if (!y) checa = 0;
      else checa = y->num;

      if (x->num > checa)
      {
         valor = x->num - checa - acarreo;
         acarreo = 0;
      }
      if (x->num < checa)
      {
         x->num += 10;
         valor = x->num - checa;
         acarreo = 1;
      }
      if (x->num == checa)
      {
         valor   = 0;
         acarreo = 0;
      }

      nodo = crea_espacio(); 
      nodo->num = valor; 
      if (!ant) {ant = nodo; salida = nodo; }
      else
      { ant->sig = nodo; nodo->ant = ant; ant = nodo;}

      x = x->sig;
      if (y) y = y->sig;
   }
   return inv(salida);
}

struct numero *multi(struct numero *a, struct numero *b)
{ 
   struct numero *x = NULL;
   struct numero *y = NULL;
   struct numero *k = NULL;
   struct numero *salida = NULL;
   struct numero *medio  = NULL;
   struct numero *nodo = NULL; 
   struct numero *ant = NULL; 
   int valor, long_a, long_b, acarreo = 0;
   int shift = 0; 
   div_t checa;

   long_a = longitud(a);
   long_b = longitud(b);

   if (long_a > long_b)  {x = inv(a); y = inv(b);}
   if (long_a < long_b)  {x = inv(b); y = inv(a);}
   if (long_a == long_b) {x = inv(a); y = inv(b);}


   while(y)
   {
      k = x;
      acarreo = 0;
      ant = NULL;
      while(k)
      {
         valor = y->num * k->num + acarreo;
         if (valor > 9)
         {
            checa   = div(valor, 10);
            acarreo = checa.quot;
            valor   = checa.rem;
         }
         else   acarreo = 0;

         nodo = crea_espacio(); 
         nodo->num = valor;
         if (!ant) {ant = nodo; medio = nodo; }
         else
         { ant->sig = nodo; nodo->ant = ant; ant = nodo;}

         k = k->sig;
      }
      if (acarreo)
      {
         nodo = crea_espacio();
         nodo->num = acarreo;
         ant->sig = nodo; nodo->ant = ant; ant = nodo;
      }
      if (shift)
      {
         acarreo = shift;
         while(acarreo)
         {
            nodo = crea_espacio();
            nodo->num = 0;
            nodo->sig = medio; medio->ant = nodo; medio = nodo;
            acarreo--;
         }
      }
      salida = suma(salida, medio);
      printf("\nva== "); imprime(salida);
      shift++;
      y = y->sig;
   }
   return inv(salida);
}

int menu(void)
{
   puts("1 suma\n"); 
   puts("2 resta\n"); 
   puts("3 producto\n"); 
   puts("4 factorial\n"); 
   scanf("%d", &operador); 
   return operador;
}


void main (void)
{
   struct numero *a, *b, *c;
   int operador;

   a = pide_numero();
   b = pide_numero();

   if (operador == 1)     c = suma(a, b);
   if (operador == 2)     c = resta(a, b);
   if (operador == 3)     c = multi(a, b);
/*   if (operador == 4)     c = facto(a, b);
*/
   imprime(c);
}