miércoles, 13 de abril de 2011

Generación de Números Aleatorios en C++

Este programa genera números aleatorios en C++ usando  las funciones rand() y srand().  He decidido generar decimales con una precisión alta en vez de enteros, aunque es muy fácil modificar este código para generar enteros, sólo elimine y e imprima x.
La instrucción 

x =  rand() % 6;

genera un número entero entre 0 y 5. Por lo tanto  la instrucción 

s = 1 + rand() % 6;

genera números aleatorios enteros entre 1 y 6. Con eso hemos resuelto nuestro problema; sin embargo rand() genera siempre el mismo número. Para hacer que el número cambie en cada corrida es necesario llamar a la función srand(). Atención, estas funciones requieren el encabezado #include <cstdlib>.  srand() hace que cada vez el número generado por rand() sea distinto, aunque necesita una semilla. Esta semilla puede introducirse por el usuario, sin embargo para evitar la incomodidad de tener que hacerlo siempre, y sobre todo si necesitan usar métodos numéricos, se introduce automáticamente como semilla la hora, tomada de la computadora, para esto se usa srand(time(NULL)). Importante: time() requiere el encabezado #include<ctime>.
Es importante tener en cuenta la instrucción setprecision(), que indica efectivamente cuántos dígitos se han de imprimir. Puede ocurrir un error sutil si se quiere generar decimales muy precisos pero no se modifica la salida estandar de precision. Para evitar esto es siempre es una buena práctica indicar directamente con qué precisión queremos la salida. Para esto se incluye #include<iomanip>.




 //ESTE PROGRAMA GENERA NUMEROS ALEATORIOS 
 //ENTRE -0.0001 Y 0.0001

 #include <iostream>
 using namespace::std;

 // Este encabezado indica que
 // se usara entrada-salida estandar

 #include <ctime>
 
 // ctime se incluye para poner como
 // semilla de srand la hora de la
 // computadora


 #include <iomanip>
 using std::setprecision;
 
 // Para imprimir los decimales
 // con la precision deseada


 enum { Tamano = 1000};

 // En este caso enum funciona como
 // #define Tamano 100




 int main()

 {      // Abre main
 
  // srand hace que  rand() genere
  // numeros distintos. Se puede hacer
  // una version en la que el usuario
  // introduzca una semilla, pero aqui
  // la semilla se introduce automaticamente
  // usando la hora de la computadora

  srand(time(NULL));
  
  double x, y;
  
  for ( int n = 1; n <= Tamano; n++)
  {          // Abre for

  x = (-5000 + rand() % 10000);
  y = x/10000; 

  cout << setprecision(10) << y << endl; 

  }     // Cierra for
 }       // Cierra main



martes, 8 de marzo de 2011

Deitel_C++_6.6 (Suma y Resta de Números Complejos en C++)

Con este programa empiezo a subir los ejercicios correspondientes a el capítulo 6 del libro Cómo Programar en C++ de Deitel y Deitel. Comparados con los capítulos anteriores no tienen una gran dificultad en la parte algorítmica. Lo importante es empezar a usar la programación orientada a objetos. También incluyo los enunciados correspondientes, algo que no había hecho. En relación a esto cabe hacer una aclaración, nunca he seguido al pie de la letra los enunciados, esto es porque he decidido hacer mucho más amables y completos los programas pensando siempre en que han de interactuar con un usuario. Así pues, las entradas de este blog no hacen exactamente lo que pide el libro.
_______________________________________________________________________________________
6.6 Cree una clase llamada Complejo para realizar aritmética con números complejos. Escriba un programa para evaluar sus clases. Los números complejos tienen la forma:
parte real + parte imaginaria*i

donde i es raíz cuadrada de -1

Utilice variables double para representar datos de tipo private de una clase. Proporcione un constructor que permita inicializar un objeto de esta clase cuando se declare. El constructor debe contener valores predeterminados en caso de que no se proporcionen inicializadores. Proporcione funciones miembro de tipo para cada uno de los siguientes:
a) Suma de dos números Complejos: las partes reales se suman juntas y las parte imaginarias se suman juntas.
b) Resta de dos números complejos: la parte real del operando derecho se resta a la parte real del operando izquierdo, y la parte imaginaria del operando derecho se resta a la parte imaginaria del operando izquierdo.
c) Impresión de números complejos de la forma (a,b) en donde a es la parte real y b es la parte imaginaria.
_______________________________________________________________________________________
Solución:

#include <iostream>
   using namespace::std; 
   // Se define la clase Complex

    class Complex
    {           // Abre la clase complex
    
    public:
    
    Complex( float = 0, float = 0);  // Constructor
    void Recibe();
    float Real();
    float Imaginario();
    void Suma(float, float, float, float);
    void Resta(float, float, float, float);

    void Impresion()
    /* Esta funcion miembro, por ser la mas simple, se definira
       aqui mismo, solo como un ejemplo de que esto puede hacerse */
    {         // Abre la funcion miembro Impresion
    cout << "( " << R << " , " << I <<" )" << endl;
    }        // Cierra la funcion miembro Impresion

    private:
    float R;
    float I; 
    };           // Cierra la clase complex

   //////////////////////////////////////////////////////////////
   // CONSTRUCTOR
   /////////////////////////////////////////////////////////////////

   Complex::Complex( float a, float b)
   {       // Abre constructor
   R = a;
   I = a;
   }         // Cierra constructor
  
   /////////////////////////////////////////////////////////////////
   // FUNCION MIEBRO RECIBE
   /////////////////////////////////////////////////////////////////

   void Complex::Recibe() 
   {          // Abre funcion miembro Recibe
   cout << "\nIntroduzca la parte real del numero: " << endl;
   cin >> R;
   cout << "\nIntroduzca la parte compleja del numero: " << endl;
   cin >> I;
   }          // Cierra funcion miembro Recibe

  ///////////////////////////////////////////////////////////////////
  // FUNCION MIEMBRO REAL
  //////////////////////////////////////////////////////////////////

  float Complex::Real()
  {
   return R;
  } 

  /////////////////////////////////////////////////////////////////
  // FUNCION MIEMBRO IMAGINARIO 
  ////////////////////////////////////////////////////////////////

  float Complex::Imaginario()

  {
   return I;
  } 

   ////////////////////////////////////////////////////////////////
   // FUNCION MIEMBRO SUMA 
   ///////////////////////////////////////////////////////////////

  void Complex::Suma( float a, float b, float c, float d)

   {            // Abre funcion miembro Suma
  cout <<"\n La suma de los numeros es:  ( "  << a + c
       << " , " << b + d 
       <<" )" << endl;
   }            // Cierra funcion miembro Suma

  //////////////////////////////////////////////////////////////
  // FUNCION MIEMBRO RESTA
  //////////////////////////////////////////////////////////////

  void Complex::Resta( float a, float b, float c, float d)

  {         // Abre funcion miembro Resta  
  cout <<"\n La resta de los numeros es:  ( " << a - c << " , " 
       << b - d 
       <<" )" << endl;
  }          // Cierra funcion miembro Resta

  ///////////////////////////////////////////////////////////////////
  // MAIN
  /////////////////////////////////////////////////////////////////

  int main()
  
  {           // Abre main
  Complex s;
  Complex x;
  Complex y;

  x.Recibe();
  y.Recibe();
  s.Suma(x.Real(), x.Imaginario(), y.Real(), y.Imaginario());  
  s.Resta(x.Real(), x.Imaginario(), y.Real(), y.Imaginario());
   
  return 0; 
  }           // Cierra main

_______________________________________________________________________________________
La siguiente es una ejecución del programa

Introduzca la parte real del numero: 
4

Introduzca la parte compleja del numero: 
3

Introduzca la parte real del numero: 
4

Introduzca la parte compleja del numero: 
3

La suma de los numeros es:  ( 8 , 6 )

La resta de los numeros es:  ( 0 , 0 )

martes, 25 de enero de 2011

Creacion de Archivo de Acceso Secuencial en C++

En esta entrada explico brevemente cómo crear un archivo de acceso secuencial en C++. Información más detallada puede encontrarse en el capítulo 14 de Cómo Programar en C++, de Deitel. Sin embargo, cuando tuve la necesidad de crear y leer archivos de datos, para trabajar con métodos numéricos, leí y adapté buena parte de la información que ahí viene. Como tengo esto en mi computadora pienso que no esta mal subirlo y que le pueda servir a alguien más. Este tipo de conocimientos son muy útiles, sobre todo, si, como en mi caso, necesitan generar una cantidad grande de información para después procesarla. Por otro lado, los usuarios de linux o unix pueden usar las herramientas que proporciona el sistema.Como se muestra Aqui

 #include <iostream>
 using namespace::std;
 // <iostream> se incluye, como en todos los programas
 // porque se usara entrada - salida
 # include <fstream>
 using std::ifstream;
 // El encabezado fstream permite crear objetos ofstream
 // e ifstream, que abren un archivo para salida y para
 // entrada, respectivamente.
 # include <cstdlib>

 int main()

 { // Abre main

 ofstream Mi_Archivo_Salida( "Mis_Datos.dat", ios::out);
// El constructor ofstream abre un archivo para escribir en el,
// es decir para enviar datos a ese archivo, mediante la creacion
// de un objeto llamado Mi_Archivo_Salida (ustedes le pueden poner el
// nombre que quieran).
// Se pasan dos argumentos al constructor del objeto, el nombre
// del archivo, que es por completo arbitrario - "Mis_Datos.dat".
// y el modo de apertura del archivo - ios::out -.
// Existen diversos modos de apertura de archivos que pueden ser usados
// a conveniencia en este caso ( apertura para envio de datos)
// a saber:
// ios::out Si el archivo "Mis_Datos.dat" existe, entonces se
// sobreescribira todo lo que entre a continuacion en ese
// archivo y se BORRARAN todos los datos previos; hay que
// estar prevenidos acerca de esto.
// Si "Mis_Datos.dat" no existe, entonces se creara un
// archivo nuevo con ese nombre.
// ios::app En este caso, si el archivo existe, entonces la nuevas
// entradas se colocan debajo de las que ya existen.
// Caso contrario, el archivo se crea.
// ios::ate Si el archivo existe, borra los datos existentes y escribe
// los nuevos, si no existe, entonces lo crea.
// ios::trunc Si el archivo existe, borra los datos existentes y escribe
// los nuevos, si no, lo crea.
// ios::in Si el archivo existe, entonces borra dos entradas del archivo
// cada vez y eventualmente sustituye todos los datos existentes,
// pero si introduce menos de la mitad de datos, entonces los nuevos
// estaran encima de los datos primitivos, hay que tener cuidado.
// Si el archivo no existe, no lo crea.

 if ( !Mi_Archivo_Salida )
 { // Abre if
 cerr << "\nEL ARCHIVO NO PUDO ABRIRSE." <<endl;
 exit( 1 );
 // Por esto se incluyo <cstdlib>
 } // Cierra if

 /* como se esta usando ios::out como modo de apertura de archivo
 podria pensarse que es inutil poner el caso de un fallo en la
 apertura, ya que de no existir se creara. Sin embargo puede ocurrir
 otro tipo de fallos, como lo que sucede si se trata, por ejemplo, de
 crear un archivo en un directorio en el que no tenemos permiso
 ( basta sustituir "Mis_Datos.dat" por "/home/Mis_Datos.dat" para
 que, en mi caso, mande el mensaje); tambien podria suceder que no
 hay memoria suficiente para crear el archivo o cualquier otra cosa,
 asi que es mejor incluir la posibilidad de fallo */

 cout << "\nIntroduzca los datos (EOF para terminar): " << endl;
 float datos;

 /* while se evalua true siempre que no se introduzca el caracter
 de fin de archivo. Esta forma compacta de recibir datos es
 dificil de entender cuando se encuentra por primera vez, pero es muy
 util. En los ejercicios de Kernighan y Ritchie del capitulo 1
 ( que se pueden ver en este mismo blog) se
 puede encontrar un buen numero de ejemplos acerca del poder de esta
 forma de usar while */

 while ( cin >> datos )
 { // Abre while
 Mi_Archivo_Salida << datos << endl;

 // asi como se introduce datos, se podria introducir mas elementos
 // dejando un espacio ' ' si fuera necesario.
 cout << endl;

 } // Cierra while

 return 0;

 }

viernes, 21 de enero de 2011

Multiplicacion de Matrices en C++

Esta entrada es un poco más simple que Multiplicacion de matrices en C , en la cual se presentan las matrices impresas, pero espero que también sea más fácil de entender. Estos ejercicios no tienen nada que ver con las soluciones a los problemas de Deitel porque no aparecen en el libro, sin embargo sí es un ejercicio obligado, y como lo he escrito lo subo por si a alguien le resulta útil. Si quiere multiplicar matrices de tamaño arbitrario entonces sólo hay que modificar las constantes M, N y P.

#include <iostream>
using namespace::std;
#define M 2 // Hay que modificar estas entradas para
#define N 3 // cambiar el tamanio de las matrices
#define P 4

// Este programa multiplica una matriz de N filas por M columnas
// con una de M filas por P columnas

/////////////////////////////////////////////////////////////
//FUNCION RECIBE_ENTRADAS1
/////////////////////////////////////////////////////////////

void Recibe_Entradas1( int Matriz[][M])

{ // Abre funcion Recibe_Entradas1

cout << "\nAqui se reciben las entradas de la primera matriz. " << endl;
cout << "De " << N << " filas y " << M << " columnas. " << endl << endl;

for ( int i = 0; i < N; i++ )
for ( int j = 0; j < M; j++ )

{ // Abre for
cout << "Introduzca el renglon " << i + 1 << " y la columna " << j + 1 << endl;
cin >> Matriz[i][j];
} // Cierra for
} // Cierra funcion Recibe_Entradas1

////////////////////////////////////////////////////////////////////////////
// ABRE FUNCION RECIBE_Entradas2
///////////////////////////////////////////////////////////////////////////

void Recibe_Entradas2( int Matriz[][P])

{ // Abre funcion Recibe_Entradas2_

cout << "\nAqui se reciben las entradas de la segunda matriz. " << endl;
cout << "De " << M << " filas y " << P << " columnas" << endl << endl;

for ( int i = 0; i < M; i++ )
for ( int j = 0; j < P; j++ )
{ // Abre for
cout << "Introduzca el renglon " << i + 1 << " y la columna " << j + 1 << endl;
cin >> Matriz[i][j];
} // Cierra for
} // Cierra funcion Recibe_Entradas2

//////////////////////////////////////////////////////////////////////////
// LA FUNCION MULTIPLICACION
//////////////////////////////////////////////////////////////////////////

// Esta es la funcion que multiplica. El problema, cuando se ve
// por primera vez parece dificil. La clave, en este y en otros problemas
// consiste en simplificarlo. Los casos limite de matrices son vectores.
// Traten primero de diseñar un algoritmo para multiplicar un vector
// renglon por un vector columna. Para hacer esto es necesario que los
// dos tengan la misma longitud. Esa multiplicacion les va a dar un numero
// y solo necesitan un indice para recorrer todas las entradas.
// Si quieren ahora multiplicar el mismo vector renglon por una matriz
// que incluya 2, 3 o mas columnas van a obtener 2, 3 o mas numeros
// en un renglon. Para esto necesitan dos subindices, uno para recorrer
// columnas y otro para recorrer el renglon. Finalmente, si en lugar de
// multiplicar un renglon por la matriz multiplican una matriz de n renglones
// por otra matriz, necesitaran 3 subindices.

void Multiplicacion( int Matriz1[][M], int Matriz2[][P], int Matriz3[][P])

{ // Abre la funcion Multiplicacion

for ( int k = 0; k < N; k++)
{ // abre primer ciclo for
for ( int j = 0; j < P; j++)
{ // abre el segundo ciclo for

for ( int i = 0; i < M; i++ )
Matriz3[ k ][j ] += Matriz1[k][i]*Matriz2[i][j];

} // Cierra el segundo ciclo for
}

} // Cierra la funcion Multiplicacion


///////////////////////////////////////////////////////////////////////////
// Funcion IMPRIMIR
//////////////////////////////////////////////////////////////////////////

void Imprimir( int Matriz[][P])

{ // Abre la funcion Imprimir

cout << endl << endl<< "Esta es la matriz producto: " << endl << endl;

for ( int i = 0; i < N; i++ )
{ // Abre for

for ( int j = 0; j < P; j++)

{ // abre for anidado

cout << Matriz[i][j] <<" \t";

} // Cierra for anidado

cout << endl << endl;

} // Cierra for


cout << endl << endl;
} // Cierra la funcion Imprimir


/////////////////////////////////////////////////////////////////////
// AQUI SE DEFINE LA FUNCION MAIN
////////////////////////////////////////////////////////////////////

int main()

{ // Abre la funcion main

int Matriz1[N][M] = {{0}};
int Matriz2[M][P] = {{0}};
int Matriz3[N][P] = {{0}};

Recibe_Entradas1( Matriz1 );
Recibe_Entradas2( Matriz2 );

Multiplicacion( Matriz1, Matriz2, Matriz3);
Imprimir(Matriz3);

return 0;
}

jueves, 20 de enero de 2011

Kernighan_Ritchie_2.1 (Valores Máximos y Mínimos de los Tipos de Datos en C)

Ejercicio 2.1 Escriba un programa que imprima los valores máximos y mínimos de los tipos de datos int, char, long, etc. de su computadora.

El lector está acostumbrado a los números enteros y reales de las matemáticas elementales. Almacenar cada uno de esos tipos en el lenguaje C requiere más o menos espacio de memoria dependiendo del tamaño de los números. Por ejemplo, representar el número 3,14159265358979323846 requiere más espacio que el almacenamiento de 20 ó -123. Para optimizar la memoria debe asignarse un tipo de dato a cada número dependiendo de su tamaño. En atención a esto tenemos los siguientes datos en C:

Los  tipos enteros:                         Memoria que los contiene
        char                                                 |-|-|
        short                                                |-|-|-|-|
        int                                                    |-|-|-|-|-|-|-|-|
        long                                                 |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
                                                       

Los tipos flotantes:
       float
       double

Los tipos de enumeración:
       enum

Los tipos de dirección:
       Apuntador
       Referencia

Los tipos estructurados:
      struct
      union
      Arreglos

Los tipos enteros guardan sólo números enteros, en tanto que los números float y double sirven para almacenar decimales.
Los tamaños relativos para los tipos de datos enteros son representados esquemáticamente en la tabla por el número de elementos de memoria. Esto no se debe de tomar tan en serio puesto que a fin de cuentas el tamaño de esos números depende de la plataforma en que se ejecute el programa (procesador, sistema operativo, compilador).  Como norma el estandar dice que los tipos short e int deben ser al menos de 16 bits y long de 32. Además short no es mayor que int, el cual a su vez no es mayor que long. A estos tipos se les puede aplicar los calificativos signed o unsigned. Siendo los unsigned números enteros no negativos. Conforme vayan apareciendo los tipos de datos se irán analizando cada uno de ellos. Por lo pronto para verificar los  valores máximos y mínimos de su computadora debe copiar, pegar, compilar y ejecutar el siguiente programa.


/* Este programa imprime los tipos maximos y minimos para los tipos int, char,
long, etc, en una computadora particular. Las constantes estan definidas en el
encabezado <limits.h> que en el libro de Kernighan y Ritchie se encuentra
descrito en el apendice B */ 

#include <stdio.h>
#include <limits.h>

int main()
{ // Abre main

printf("\nEl valor minimo del tipo char en esta computadora es: %d\n", CHAR_MIN);
printf("\nEl valor maximo del tipo char en esta computadora es: %d\n", CHAR_MAX);
printf("\nEl valor minimo del tipo int en esta computadora es: %d\n", INT_MIN);
printf("\nEl valor maximo del tipo int en esta computadora es: %d\n", INT_MAX);
printf("\nEl valor minimo del tipo long en esta computadora es: %d\n", LONG_MIN);
printf("\nEl valor maximo del tipo long en esta computadora es: %d\n", LONG_MAX);
printf("\nEl valor maximo del tipo unsigned int en esta computadora es: %d\n", UINT_MAX);

return 0;
} // Cierra main
__________________________________________________________________________________ 
Ahora hagamos un análisis del programa línea por línea para revisar cada instrucción.
/* Este programa imprime los tipos maximos y minimos para los tipos int, char,
long, etc, en una computadora particular. Las constantes estan definidas en el
encabezado <limits.h> que en el libro de Kernighan y Ritchie se encuentra
descrito en el apendice B */ 
Estas tres líneas son un comentario con información general sobre el programa. Recuerde que los comentarios en C empiezan con /* y terminan con */ Recuerde también que es una buena idea comentar los programas. Este comentario en particular hace referencia a un clásico de la programación en C: El Lenguage de Programación C, un libro de B. Kernighan y Dennis Ritchie, creadores del lenguaje.
#include <stdio.h>
Para incluir un encabezado cualquiera debe hacer uso de #include. A continuación debe utilizar el nombre del encabezado necesario. stdio.h incluye varias funciones y utilidades que serán necesarias. Siempre que use entrada o salida de datos debe incluirlo.
#include <limits.h>
Los tamaños máximos y mínimos de los tipos de datos en cualquier plataforma particular están definidos en este encabezado mediante las constantes CHAR_MIN, CHAR_MAX, etc.
int main()
{ // Abre main
La función main aparece en todos los programas. Se trata, como su nombre en inglés lo dice, de la función principal. Todas las funciones reciben y entregan datos. int es el tipo de datos que main entrega. Los paréntesis vacíos indican que la función main no recibe ningún dato. El cuerpo de main, como el de todas las funciones, está delimitado por llaves { } La forma de comentar que aparece aquí es nueva. El compilador pasa por alto todo lo que se encuentra después de //, estos caracteres inclusive. El comentario termina con el primer salto de línea. A pesar de que la forma estándar de comentar es usando /* */ practicamente todos los compiladores son capaces de reconocer comentarios con // (una forma de comentario propia del lenguaje C++)
printf("\nEl valor minimo del tipo char en esta computadora es: %d\n", CHAR_MIN);
printf("\nEl valor maximo del tipo char en esta computadora es: %d\n", CHAR_MAX); printf("\nEl valor minimo del tipo int en esta computadora es: %d\n", INT_MIN); printf("\nEl valor maximo del tipo int en esta computadora es: %d\n", INT_MAX); printf("\nEl valor minimo del tipo long en esta computadora es: %d\n", LONG_MIN); printf("\nEl valor maximo del tipo long en esta computadora es: %d\n", LONG_MAX); printf("\nEl valor maximo del tipo unsigned int en esta computadora es: %d\n", UINT_MAX);
Estas líneas hacen uso de la función printf para imprimir los máximos y mínimos valores de algunos tipos de datos. Como hemos visto, la secuencia de escape \n indica nueva línea. Esto es, el cursor se coloca al inicio del siguiente renglón. Después de la instrucción printf todo lo que viene a continuación está contenido entre paréntesis, y termina con punto y coma. La estructura es printf( ); Todo lo que se coloque dentro de los paréntesis y entre comillas dobles se imprimirà, salvo que sea una secuencia de escape o una referencia a una variable. Para imprimir enteros es necesario usar %d entre las comillas, después de las comillas es necesario colocar una coma y la variable entera (o variables enteras separadas por comas).
return 0;
La función main retorna un entero. El entero que retorna es 0. Esta instrucción debe ir siempre al final del programa. Indica que se han terminado las instrucciones.
} // Cierra main
Con el cierre de las llaves se termina el cuerpo de main. __________________________________________________________________________________ 
Lo que aprendió: 
Los tipos de datos en C 
Los valores máximos y mínimos de cada tipo básico en su plataforma.
Los comentarios usando //
____________________________________________________________________________________________
Esta entrada forma parte del Curso de C con Programas Explicados Línea por Línea
Índice
Entrada Anterior
Entrada Siguiente
Related Posts Plugin for WordPress, Blogger...