miércoles, 29 de junio de 2011

Representación De Los Enteros Con Signo En Complemento A Dos

Esta entrada pretende responder a una pregunta básica: ¿Cómo representan las computadoras a un número entero con signo?. Supongamos que nuestra computadora asigna 4 bits para la representación de estos números ( esto, desde luego, es una caricatura; en el lenguaje C el tamaño de un entero es por lo menos de 16 bits, aunque depende de la computadora, puede ver el tamaño de sus int usando este programa: Tipos de Datos en C; en tanto que en Java está fijo a 32 bits, lo cual es demasiado para nuestros fines didácticos). En una base binaria esto significa que podemos representar números del 0 ( 0000 ) al 15 (1111). Ahora bien, esos 16 símbolos distintos tienen que representar un rango de números positivos y negativos (presumiblemente de -7 a 7).

Atendiendo puramente a la representación a uno se le puede ocurrir lo siguiente:

Representación en la forma Magnitud con Signo:

Es, de cierta manera, lo más natural. Consiste en reservar la posición de la izquierda extrema para el signo con la convención de que 0 indica un entero positivo y 1 indica un entero negativo.

Binario       Magnitud con Signo

  0000               0
  0001               1
  0010               2
  0011               3
  0100               4
  0101               5
  0110               6
  0111               7
  1000              -0
  1001             - 1
  1010              -2
  1011             - 3
  1100             - 4
  1101             - 5
  1110             - 6
  1111             - 7


Representación en Complemento a Uno

Es un poco más ingeniosa y consiste en "invertir" la representación. Para obtener -3 es necesario tomar 3 ( 0011 ) y escribir un nuevo número cambiando los 1 por 0 y los 0 por uno, así se obtiene (1100)

  Binario       Complemento a Uno

  0000               0
  0001               1
  0010               2
  0011               3
  0100               4
  0101               5
  0110               6
  0111               7
  1000              -7
  1001              -6 
  1010              -5
  1011              -4
  1100              -3
  1101              -2
  1110              -1
  1111              -0


Inconvenientes de las representaciones Magnitud con Signo y Complemento a Uno:

Ahora bien, este par de representaciones tiene algunos problemas: existen 2 símbolos distintos para el 0 y no permiten operar aritméticamente.

En la representación Magnitud con Signo, intentemos sumar 7 + (-2)

0111 (7)
1010 (-2)
___________
0001 (1)


Pero 7 - 2 != 1

En la representación Complemento a Uno

0111 (7)
1101 (-2)
___________
0100 (4)

Pero 7 - 2 != 4 Observe además que aquí ha ocurrido un "acarreo", el resultado de la suma es 10100, pero como usamos 4 bits eso no importa, ya que tomamos los primeros 4 valores de la derecha.

Aún con estos problemas es posible, y se ha hecho en el pasado, usar estas representaciones para almacenar números con signo en computadoras electrónicas. Sin embargo, hacer hardware para sumar (diseñar circuitos lógicos) es demasiado complicado en estos casos. Por eso, actualmente la gran mayoría de las computadoras usan la siguiente representación.

Representación en Complemento a Dos:

Como se ha visto, es muy deseable que la representación sea tal que cuando se suma un número positivo con su negativo, el resultado sea 0000.  Por ejemplo, ya que 5 se representa como 0101, a -5 se le asigna 1011, ya que la suma es 10000, la cual truncada a los primeros 4 bits, da 0 (0000). Usando esto como guía es posible establecer la siguiente tabla


  Binario      Complemento a Dos

  0000               0
  0001               1
  0010               2
  0011               3
  0100               4
  0101               5
  0110               6
  0111               7
  1000              -8
  1001              -7
  1010              -6
  1011              -5
  1100              -4
  1101              -3
  1110              -2
  1111              -1

Además, algo muy importante, podemos ver que en este caso si se ordenan los números de -7 a 7, el siguiente se obtiene sumando 1 al número anterior, por lo mismo al símbolo 1000 se le asigna el valor -8, que encaja perfectamente.

 Binario      Complemento a Dos

  1000              -8
  1001              -7
  1010              -6
  1011              -5
  1100              -4
  1101              -3
  1110              -2
  1111              -1
  0000               0
  0001               1
  0010               2
  0011               3
  0100               4
  0101               5
  0110               6
  0111               7

Esto garantiza que la suma de números dentro del rango de -8 a  7, se hará de forma correcta.  Obsérvese que esta representación es muy parecida a la Representación en Complemento a Uno, y que, como algoritmo, para encontrar el negativo de un número, digamos 5 (0101) sólo es necesario encontrar el Complemento a Uno, cambiando 1 por 0 y viceversa, (1010) y sumar 0001, con lo cual obtenemos -5 (1011). Las sumas producen "acarreo", por ejemplo -3  (1101) -3 (1101) es igual a    11010, pero como sólo estamos trabajando en 4 bits, el resultado se trunca y se obtiene -6 (1010), lo cual es correcto. El acarreo es lo que origina el desbordamiento de la memoria en la suma de dos numeros muy grandes. Si en java, o en cualquier otro lenguaje, se suma un par de enteros muy grandes (2147483640 + 2147483640) se obtiene la respuesta -1932700016. Esta no es, desde luego, la respuesta correcta. Lo que ha pasado es que los números están en el límite superior de lo que puede almacenar un int en java. El signo menos viene porque en la entrada extrema izquierda, el bit 32, hay un 1 (que indica número negativo) en lugar de un 0 (que indica número positivo) así pues, la suma se trunca, se convierte a decimal y se cambia de signo. Creo que este ejemplo en particular muestra la importancia de saber algo acerca de la forma en que se almacenan los enteros en una computadora.
El uso de la Representación en Complemento a Dos es, por cierto, lo que hace que, por ejemplo, en Java los tipos int varíen en un rango de -2147483648 a  2147483647, se reserva el bit 32 para el signo y las siguientes magnitudes dependen de los 31 bits restantes  (2^31 = 2147483648). Si usted, como yo, se había preguntado alguna vez por qué el rango no es simétrico, o por qué  no va de -2147483647 a 2147483648, espero que esta entrada le haya servido para resolver esa duda.
______________________________________________________________________________________________
Lo que aprendió:
La representación de los números con signo en la forma Magnitud con Signo
La representación de los números con signo en Complemento a 1
La representación de los números con signo en Complemento a 2
______________________________________________________________________________________________
Esta entrada forma parte del Curso de C con Programas Explicados Línea por Línea
Índice
Entrada Anterior
Entrada Siguiente

martes, 28 de junio de 2011

Deitel_Java_6.31 (Instrucción Asistida por Computadora en Java)

_____________________________________________________________________________________
6.31 El uso de las computadoras en la educación se conoce como instrucción asistida por computadora, CAI por sus siglas en inglés. Un problema que se desarrolla en los entornos CAI es la fatiga de los estudiantes. Este problema puede eliminarse si se varía el diálogo de la computadora para mantener la atención del estudiante. Modifique el programa del Ejercicio_6_30 de manera que los diversos comentarios se impriman para cada respuesta correcta e incorrecta de la siguiente manera:

Contestaciones a una respuesta correcta:

Muy bien!
Excelente!
Buen trabajo!
Sigue así!

Contestaciones a una respuesta incorrecta:

No. Por favor intenta de nuevo.
Incorrecto. Intenta una vez mas.
No te rindas.
No. Sigue intentando.

Use la generación de números aleatorios para elegir un número entre 1 y 4 que se utilice para seleccionar una contestación apropiada a cada respuesta. Use una instrucción switch para emitir las contestaciones.
_____________________________________________________________________________________
Éste programa es bastante completo y fácil de usar.

Este código debe guardarse con el nombre UsaDeitel_6_31.java
 public class UsaDeitel_6_31

 {       // Abre clase UsaDeitel_6_31

 public static void main(String args[])

 {            // Abre main
 Deitel_6_31 miObjeto = new Deitel_6_31();
 miObjeto.Pregunta();
 
 System.out.println("\nHasta luego!");
 }            // Cierra main
   
 }         // Cierra clase UsaDeitel_6_31

El siguiente código debe guardarse con el nombre Deitel_6_31.java

 import java.util.Random;
 import java.util.Scanner;

 public class Deitel_6_31

 {      // Abre clase Deitel_6_31


 public void Pregunta()
 
 {    // Abre metodo Pregunta
 Scanner recibe = new Scanner(System.in);

 int respuesta; 
 do 
 {   // Abre do
 Genera();

 System.out.println("\nQuiere volver a intentar?");
 System.out.println("Introduzca un numero (-1 para terminar)");
 respuesta = recibe.nextInt();

 }   // Cierra do
 while ( -1 != respuesta );
 }    //
 
 public void Genera()

 {        // Abre metodo Genera
 Random salida = new Random();
 Scanner entrada = new Scanner(System.in);
 int numero1;
 int numero2;
 int respuesta;
 int Escala = 9;
 int auxiliar;

 numero1 = 1 + salida.nextInt(Escala);
 numero2 = 1 + salida.nextInt(Escala);

 do
 {       // Abre while
 System.out.printf("\nCuanto es %d * %d?\n", numero1, numero2 );
 respuesta = entrada.nextInt();

 if ( numero1*numero2 != respuesta )
 {       // Abre if
 auxiliar = 1 + salida.nextInt(4);

 switch (auxiliar) 
 {     // Abre switch
 case 1:
 System.out.println("\nNo. Por favor intenta de nuevo!");
 break;

 case 2:
 System.out.println("\nIncorrecto. Intenta una vez mas!");
 break;
  
 case 3:
 System.out.println("\nNo te rindas!");
 break;

 case 4:
 System.out.println("\nNo. Sigue intentando!");
 break;
 }     // Cierra switch


 }       // Cierra if
 
 }    // Cierra while
 while( numero1*numero2 != respuesta);

 // Si la respuesta ha sido correcta
 
 auxiliar = 1 + salida.nextInt(4);
 switch (auxiliar) 
 {     // Abre switch
 case 1:
 System.out.println("\nMuy bien!");
 break;

 case 2:
 System.out.println("\nExcelente!");
 break;
  
 case 3:
 System.out.println("\nBuen trabajo!");
 break;

 case 4:
 System.out.println("\nSigue asi!");
 break;
 }     // Cierra switch

 }        // Cierra metodo Genera

 }      // Cierra clase Deitel_6_31

lunes, 27 de junio de 2011

Deitel_Java_6.30 (Aprendiendo las Tablas de Multiplicar en Java)

_____________________________________________________________________________________
6.30 Las computadoras están tomando un papel cada vez más importante en la educación. Escriba un programa que ayude a un estudiante de la escuela primaria, para que aprenda a multiplicar. Use un objeto Random para producir dos enteros positivos de un signo. El programa debe entonces mostrar una pregunta al usuario, como:

Cuanto es 6 * 7?

El estudiante entonces debe escribir la respuesta. Luego, el programa debe verificar la respuesta del estudiante. Si es correcta, dibuje la cadena "Muy bien!" y haga otra pregunta de multiplicación. Si la respuesta es incorrecta, dibuje la cadena "No. Por favor intenta de nuevo." y deje que el estudiante intente la misma pregunta varias veces, hasta que esté correcta. Debe utilizarse un método separado para generar cada pregunta nueva. Este método debe llamarse una vez cuando la aplicación empiece a ejecutarse, y cada vez que el usuario responda correctamente a la pregunta.
_____________________________________________________________________________________
SOLUCIÓN:
Éste programa es simple en su construcción. El siguiente presenta una mejora con respecto a las opciones de diálogo con el usuario.

El código siguiente tiene que guardarse con el nombre UsaDeitel_6_30.java

public class UsaDeitel_6_30

{       // Abre clase UsaDeitel_6_30

public static void main(String args[])

{            // Abre main
Deitel_6_30 miObjeto = new Deitel_6_30();
miObjeto.Pregunta();
}            // Cierra main
}       // Cierra clase UsaDeitel_6_30

El código siguiente tiene que guardarse con el nombre UsaDeitel_6_30.java

import java.util.Random;
import java.util.Scanner;

public class Deitel_6_30

{      // Abre clase Deitel_6_30


public void Pregunta()
 
{    // Abre metodo Pregunta
Scanner recibe = new Scanner(System.in);

int respuesta; 
do 
{   // Abre do
Genera();

System.out.println("\nQuiere volver a intentar?");
System.out.println("Introduzca un numero (-1 para terminar)");
respuesta = recibe.nextInt();

}   // Cierra do
while ( -1 != respuesta );
}    // Cierra Pregunta
 
public void Genera()

{        // Abre metodo Genera
Random salida = new Random();
Scanner entrada = new Scanner(System.in);
int numero1;
int numero2;
int respuesta;
int Escala = 9;

numero1 = 1 + salida.nextInt(Escala);
numero2 = 1 + salida.nextInt(Escala);

do
{       // Abre while
System.out.printf("\nCuanto es %d * %d?\n", numero1, numero2 );
respuesta = entrada.nextInt();

if ( numero1*numero2 != respuesta )
System.out.println("\nNo. Por favor intenta de nuevo.");
 
}    // Cierra while
while( numero1*numero2 != respuesta);

System.out.println("\nMuy bien!");

}        // Cierra metodo Genera

}      // Cierra clase Deitel_6_30

Deitel_Java_6.29 (Lanzamiento de una Moneda en Java)

6.29 Escriba una aplicación que simule el lanzamiento de una moneda. Cuente el número de veces que aparece cada uno de los lados de la moneda. [Nota: si el programa simula de manera realista el lanzamiento de monedas, cada lado de la moneda debe aparecer aproximadamente la mitad del tiempo.]
El siguiente código debe guardarse como UsaDeitel_6_29.java

 public class UsaDeitel_6_29

 {    // Abre clase UsaDeitel_6_29
 public static void main(String args[])

 {           // Abre main
 Deitel_6_29 miObjeto = new Deitel_6_29();

 System.out.println("\nEste programa simula lanzamientos de una moneda.");

 miObjeto.Lanzamiento();

 }           // Cierra main
 }    // Cierra clase UsaDeitel_6_29

El siguiente código debe guardarse con el nombre Deitel_6_29.java

 import java.util.Random;
 import java.util.Scanner;

 public class Deitel_6_29

 {  // Abre clase Deitel_6_29
 
 public void Lanzamiento()
 {      // Abre metodo Lanzamiento

 Random aleatorios = new Random();
 int numero;
 int Escala = 2;
 int contadorCara = 0;
 int contadorCruz = 0; 
 int centinela = 0;
 Scanner entrada = new Scanner(System.in);

 while ( -1 != centinela )
 {      // Abre while
 numero =  aleatorios.nextInt(Escala); 

 if ( 0 == numero )
 {    // Abre if
 contadorCara++;
 System.out.println("\nEl resultado del lanzamiento es cara.");
 }    // Cierra if
 else
 {    // Abre else 
 contadorCruz++;
 System.out.println("\nEl resultado del lanzamiento es cruz.");
 }    // Cierra else

 System.out.println("\nQuiere volver a lanzar una moneda?");
 System.out.println("\nIntroduzca un entero, -1 para terminar.");
 centinela = entrada.nextInt();

 }      // Cierra while

 System.out.printf("\nEl numero de caras es: %d\n", contadorCara);
 System.out.printf("\nEl numero de cruces es: %d\n", contadorCruz);

 return;
 }      // Cierra metodo Lanzamiento

 }    // Cierra clase Deitel_6_29

Deitel_Java_6.28 (Evaluando Promedios de un Alumno en Java)

6.28 Escriba un método llamado Calidad que reciba como entrada el promedio de un estudiante y devuelva 4 si el promedio se encuentra entre 90 y 100,  3 si el promedio se encuentra entre 80 y 89, 2 si el promedio se encuentra entre 70 y 79, 1 si el promedio se encuentra entre 60 y 69, y 0 si el promedio es menor de 60. Incorpore el método en una aplicación que reciba como entrada un valor del usuario y muestre el resultado.

El siguiente código debe guardarse con el nombre UsaDeitel_6_28.java

 import java.util.Scanner;

 public class UsaDeitel_6_28

 {   // Abre UsaDeitel_6_28

 public static void main(String args[])
 {    // Abre main

 int numero1;
 int numero2;
 Scanner entrada = new Scanner(System.in);
 Deitel_6_28 miObjeto =  new Deitel_6_28();

 System.out.print("\nEste programa recibe los aciertos del");
 System.out.print(" alumno y muestra la calificacion. ");

 System.out.println("\nPor favor introduzca la calificacion del alumno.");
 numero1 = entrada.nextInt();

 do
 {     // Abre while 
 numero2 = miObjeto.Calidad(numero1);

 System.out.printf("\nLa calificacion del alumno es: %d\n", numero2);
         
 System.out.println("\nPor favor introduzca la calificacion del alumno.");
 System.out.println("-1 para terminar. ");
 numero1 = entrada.nextInt();

 }    // Cierra while 

 while ( -1 != numero1 && ( 0 <= numero1 && 100 >= numero1));

 }        // Cierra main
 }   // Cierra UsaDeitel_6_28

El siguiente código debe guardarse con el nombre Deitel_6_28.java

 public class Deitel_6_28

 {         // Abre clase Deitel_6_28
 
 public int Calidad( int x )
 {    // Abre metodo Calidad
 
 if ( 90 <= x && 100 >= x )
 {
 return 4;
 }
 if ( 80 <= x && 89 >= x )
 {
 return 3;
 }
 if ( 70 <= x && 79 >= x )
 {
 return 2;
 } 
 if ( 60 >= x && 69 >= x )
 {
 return 1;
 } 
 if ( 60 > x )
 {
 return 0;
 } 

 return -1;
 }    // Cierra metodo Calidad

 }         // Cierra clase Deitel_6_28

Deitel_Java_6.27 (algoritmo de Euclides en Java)

_______________________________________________________________________________________________________________________
6.27 El máximo común divisor (MCD) de dos enteros es el entero más grande que puede dividir uniformemente a cada uno de los dos números. Escriba un método llamado Mcd que devuelva el máximo común divisor de dos enteros. (Sugerencia: tal vez sea conveniente que utilice el algoritmo de Euclides. Incorpore el método a una aplicación que reciba como entrada dos valores y muestre el resultado.
_______________________________________________________________________________________________________________________
Solución:
También puede ver Algoritmo de Euclides en C++

Este código debe guardarse con el nombre UsaDeitel_6_27.java


 import java.util.Scanner;

 public class UsaDeitel_6_27

 {     // Abre clase UsaDeitel_6_27
 
 public static void main(String args[])
 {       // Abre main

 Scanner entrada = new Scanner(System.in);
 int numero1; //numero1 y numero2 se utilizan para recibir 
 int numero2;  // las entradas del usuario.
 int auxiliar; // Este numero recibe el mcd del metodo Mcd
 Deitel_6_27 miObjeto = new Deitel_6_27(); 

 System.out.printf("\nEste programa utiliza el algoritmo de Euclides ");
 System.out.println("para encontrar el maximo comun divisor de dos numeros.\n");
 System.out.printf("\nPor favor introduzca un par de numeros enteros: ");
 numero1 = entrada.nextInt();
 numero2 = entrada.nextInt();

 auxiliar = miObjeto.Mcd( numero1, numero2 );  
 System.out.printf("\nEl maximo comun divisor de %d y %d es: %d\n", numero1, numero2, auxiliar); 
 System.out.println("\n");
 }     // Cierra main
 }     // Cierra clase UsaDeitel_6_27

El siguiente código debe guardarse con el nombre Deitel_6_27.java

 public class Deitel_6_27

 {     // Abre clase Deitel_6_27

 public int Mcd( int x, int y)

 {         // Abre metodo Mcd
 int temporal;

 while ( x > 0 )
 {         // Abre while
 
 if (  x < y )
 {   // Abre if
 temporal = x;
 x = y;
 y = temporal;
 }   // Cierra if

 x = x - y;
 }         // Cierra whie

 return y;
 }         // Cierra metodo Mcd
 }     // Cierra clase Deitel_6_27

Deitel_Java_6.26 (Invertir los Dígitos de un Número en Java)

6.26  Escriba un método que tome un valor entero y devuelva el número con sus dígitos invertidos. Por ejemplo, para el número 7631, el método debe regresar 1367. Incorpore el método en una aplicación que reciba como entrada un valor del usuario y muestre el resultado.

Este código también aparece resuelto en C++: Deitel_C++_3.31
Este código debe guardarse con el nombre UsaDeitel_6_26.java

 import java.util.Scanner;

 public class UsaDeitel_6_26

 {      // Abre clase UsaDeitel_6_26
 
 public static void main(String args[])
 {           // Abre main

 Scanner entrada = new Scanner(System.in);
 int numero;
 Deitel_6_26 miObjeto = new Deitel_6_26();


 System.out.println("\nEste programa recibe un entero y lo presenta con los ");
 System.out.println("digitos invertidos. ");
 System.out.println("\nPor favor introduzca un numero: ");
 numero = entrada.nextInt();

 System.out.println("\nEste es el numero invertido:\n ");
 miObjeto.Invierte( numero );

 
 }           // Cierra main 
 }      // Cierra clase UsaDeitel_6_26

El siguiente código debe guardarse con el nombre Deitel_6_26.java

 public class Deitel_6_26

 {        // Abre clase Deitel_6_26

 public int Cuenta( int x )

 {         // Abre metodo Cuenta 
 //Lo primero que se hace es averiguar cuantos digitos tiene 
 //el numero. Para esto se hace lo siguiente:
 //se divide el numero sucesivamente entre 1, 10, 100,....
 //mientras el resultado sea distinto de cero.
 //Al mismo tiempo se incrementa una variable contador
 //que cuenta el numero de digitos.
 //Cuando finalmente se alcanza un cero quiere decir que 
 //se ha dividido entre un multiplo de 10 mayor al numero
 //y por lo tanto se deja de contar. Sin embargo, se ha contado
 //de mas una vez, por lo cual se resta una unidad.
 //El siguiente segmento realiza esta tarea.
  
 int divisor = 1;
 int contador = 0; 
 int digito = 1;

 while ( 0 != digito )
 {      // Abre while
  
 digito = x / divisor;
 divisor *= 10;
 contador++;

 }      // Cierra while 

 return --contador;

 }         // Cierra metodo Cuenta


 //////////////////////////////////////////////////////////
 //METODO INVIERTE
 /////////////////////////////////////////////////////////

 public void Invierte (int y ) 

 {         // Abre metodo Invierte

 // Par dar una idea de la forma en que se obtienen los
 // digitos, es bueno poner el siguiente ejemplo
 //
 // sea y = 37401
 //
 // Digito1 = 37401 % 10
 // Digito2 = ((37401)/10) % 10 
 // Digito3 = (((37401)/10)/10) % 10
 // Digito4 = ((((37401)/10)/10)/10) %10
 // Digito5 = ((((37401)/10/)10)/10)/10
 
 int digitos = Cuenta(y);

 for (int i = 1; i < digitos; i++)
 {       // Abre for
 System.out.printf("\t%d", y % 10);     
 y /= 10;
          
 }       // Cierra for 

 System.out.printf("\t%3d", y);
 System.out.println("\n");

 }         // Cierra metodo Invierte
 }        // Cierra clase Deitel_6_26

domingo, 26 de junio de 2011

Una Idea Muy Importante A La Hora De Comprar Una Computadora

Lo siguiente está tomado literalmente del libro Introducción a los Sistemas de Cómputo. De los Bits y las Compuertas al C y Más Allá. Segunda Edición, de Yale N. Patt y Sanjay J. Patel. McGraw Hill. Creo que puede servir de consuelo a quienes, como yo, tienen una máquina no muy reciente.

"Todas las computadoras ( la más grande y la más pequeña, la más rápida y la más lenta, la más cara y la más barata ) son capaces de calcular exactamente las mismas cosas si se les da tiempo y memoria suficientes. Esto es, cualquier cosa que una computadora rápida puede hacer, una computadora lenta también puede hacerla. La computadora lenta simplemente lo hace más lento. Una computadora más cara no puede calcular algo que una computadora barata no puede calcular, siempre y cuando la computadora barata tenga acceso a memoria suficiente. (Es posible que tenga que ir a la tienda a comprar discos cuando se quede sin memoria con el fin de aumentarla.) Todas las computadoras pueden hacer exactamente las mismas cosas. Algunas computadoras pueden hacer las cosas más rápido, pero ninguna puede hacer más cosas que otra."

sábado, 25 de junio de 2011

Deitel_Java_6.25 c) (Números Primos entre 1 y 1000 en Java)

6.25 c) Este programa imprime los primos menores a 10000. Al principio podría pensarse que n/2 es el límite superior para evaluar si un número es primo (como ocurre en  Deitel_Java_6_25.b), pero lo máximo que se necesita es ir hasta la raíz cuadrada de n. ¿Por qué?. Debido a la cantidad de líneas de salida, es conveniente Redireccionar la Salida.

Este código debe guardarse con el nombre UsaDeitel_6_25.java


 public class UsaDeitel_6_25

 {    // Abre UsaDeitel_6_25

 public static void main(String args[])

 {        // Abre main 

 Deitel_6_25 miObjeto = new Deitel_6_25();
 String auxiliar;
 int Tamano = 10000;

 System.out.printf("\nEste programa imprime los primos entre 1 y %d \n", Tamano);


 for ( int i = 2; i <= Tamano; i++ )
 {         // Abre for
 auxiliar = miObjeto.Primo(i);

 if ( "primo" == auxiliar )
 System.out.printf("%d \n", i );

 }      // Cierra for

 }        // Cierra main
 }    // Cierra UsaDeitel_6_25


El siguiente código debe guardarse como Deitel_6_25.java

 // Esta clase contiene un metodo 
 // que recibe un entero x,  evalua si se
 // trata de un primo o no y regresa esa
 // informacion en forma de una cadena 
 
 public class Deitel_6_25

 {  // Abre clase Deitel_6_25

 public String Primo( int x)

 {            // Abre metodo Primo
 String Estatus = "primo";
 // En principio se concede que el numero
 // recibido es primo, por eso la variable
 // Estatus se inicializa con "primo"
 
 // En este for solo se llega hasta la raiz cuadrada
 // del numero. 
 for ( int i = 2; i <= (int) Math.sqrt(x); i++ )
 {      // Abre for

 // Si el ciclo for empieza desde 1, entonces el
 // Estatus siempre se cambia a "compuesto", ya que
 // todos los numeros son divisibles entre 1
 

 if ( 0 == x % i )
 Estatus = "compuesto";

 // Si el x es divisible entre cualquier otro numero, 
 // entonces es "compuesto"
 
 }      // Cierra for
 return Estatus;
 }            // Cierra metodo Primo

 }  // Cierra clase Deitel_6_25

Deitel_Java_6.25 b) (Números Primos entre 1 y 10000 en Java)

_____________________________________________________________________________________
6.25 b) Cree una aplicación que determine e imprima todos los números primos menores que 10000.
_____________________________________________________________________________________
SOLUCIÓN:
Este problema usa la misma clase que aparece en Deitel_Java_6.25 a. Una versión mejorada de éste programa se da en Deitel_6_25 c. Debido a que este programa genera 1231 líneas de salida, tal vez le convenga Redireccionar la salida.

Este código debe guardarse con el nombre  UsaDeitel_6_25.java

public class UsaDeitel_6_25

{    // Abre UsaDeitel_6_25

public static void main(String args[])

{        // Abre main 

Deitel_6_25 miObjeto = new Deitel_6_25();
String auxiliar;
int Tamano = 10000;

System.out.printf("\nEste programa imprime los primos entre 1 y %d \n", Tamano);

for ( int i = 2; i <= Tamano; i++ )
{         // Abre for
auxiliar = miObjeto.Primo(i);

if ( "primo" == auxiliar )
System.out.printf("%d \n", i );
}      // Cierra for

}        // Cierra main

}    // Cierra UsaDeitel_6_25

Este código debe guardarse con el nombre  Deitel_6_25.java

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++
*  Esta clase contiene un metodo que recibe un entero x,+ 
*  evalua si se trata de un primo o no y regresa esa    +
*  informacion en forma de una cadena.                  +
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
   
 
public class Deitel_6_25

{  // Abre clase Deitel_6_25

public String Primo( int x)

{            // Abre metodo Primo
String Estatus = "primo";
// En principio se concede que el numero
// recibido es primo, por eso la variable
// Estatus se inicializa con "primo"
 

for ( int i = 2; i <= x / 2 ; i++ )
{      // Abre for

// Si el ciclo for empieza desde 1, entonces el
// Estatus siempre se cambia a "compuesto", ya que
// todos los numeros son divisibles entre 1
 
if ( 0 == x % i )
Estatus = "compuesto";

// Si el x es divisible entre cualquier otro numero, 
// entonces es "compuesto"
 
}      // Cierra for

return Estatus;
}            // Cierra metodo Primo

}  // Cierra clase Deitel_6_25

Deitel_Java_6.25 a) (Determinar si un número es primo en Java)

6.25 a) Se dice que un entero es primo si puede dividirse solamente por 1 y por sí mismo. Por ejemplo, 2, 3, 5 y 7 son primos , pero 4, 6, 8 y 9 no. Escriba un método que determine si un número es o no primo.

Este código debe guardarse con el nombre UsaDeitel_6_25.java
 import java.util.Scanner;

 public class UsaDeitel_6_25

 {    // Abre UsaDeitel_6_25

 public static void main(String args[])

 {        // Abre main 
 Scanner entrada = new Scanner(System.in);
 Deitel_6_25 miObjeto = new Deitel_6_25();
 int numero;
 String auxiliar;


 System.out.println("\nEste programa recibe un numero y determina si es");
 System.out.println("primo o no.");

 do
 {        //Abre do
 System.out.println("\nPor favor introduzca un entero positivo. ");
 numero = entrada.nextInt();
 }       // Cierra do
 while ( 0  >=  numero ); 

 auxiliar = miObjeto.Primo(numero);

 if ( "primo" == auxiliar )
 System.out.printf("\nEl numero %d es primo\n", numero);

 else 
 System.out.printf("\nEl numero %d no es primo\n", numero);


 }        // Cierra main
 }    // Cierra UsaDeitel_6_25

El siguiente código debe guardarse con el nombre Deitel_6_25.java

 // Esta clase contiene un metodo 
 // que recibe un entero x,  evalua si se
 // trata de un primo o no y regresa esa
 // informacion en forma de una cadena 
 
 public class Deitel_6_25

 {  // Abre clase Deitel_6_25

 public String Primo( int x)

 {            // Abre metodo Primo
 String Estatus = "primo";
 // En principio se concede que el numero
 // recibido es primo, por eso la variable
 // Estatus se inicializa con "primo"
 

 for ( int i = 2; i <= x / 2 ; i++ )
 {      // Abre for

 // Si el ciclo for empieza desde 1, entonces el
 // Estatus siempre se cambia a "compuesto", ya que
 // todos los numeros son divisibles entre 1
 

 if ( 0 == x % i )
 Estatus = "compuesto";

 // Si el x es divisible entre cualquier otro numero, 
 // entonces es "compuesto"
 
 }      // Cierra for
 return Estatus;
 }            // Cierra metodo Primo

 }  // Cierra clase Deitel_6_25

viernes, 24 de junio de 2011

Ordenamiento de Burbuja en C++

El ordenamiento burbuja es un algoritmo simple para ordenar los elementos de un arreglo. Consiste en ir comparando cada entrada con la siguiente e intercambiar sus posiciones en caso de que no estén ordenados. La primera pasada garantiza que el elemento más grande vaya hasta el último elemento del algoritmo, en la segunda el segundo mayor, y así sucesivamente los elementos grandes van "subiendo" como las burbujas en un líquido. El programa presentado aquí es el básico. Se puede hacer más eficiente tomando en cuenta ciertos aspectos. Aquí se considera el peor de los casos; sin embargo podría suceder que el arreglo ya estuviera total o parcialmente ordenado, en tal situación este algoritmo de todas formas cumple con los dos ciclos, lo cual desde luego no es apropiado. Las mejoras, sin embargo, corresponden a otras entradas, ( Ordenamiento Burbuja Mejorado ) La principal característica de ésta versión es su sencillez.
El siguiente video explica bien de qué se trata este algoritmo.





 #include <iostream>
 using namespace::std;

 enum { Tamano = 10};
 // Cambiar la variable Tamano para ordenar una
 // cantidad diferente de datos
 

 /*Prototipo de funcion Imprime */
 void Imprime( int A[]);

 /*prototipo de funcion Recibe */
 void Recibe ( int B[]);

 /*Prototipo de funcion Burbuja */
 void Burbuja( int C[]);
 

 int main()

 {           // Abre main

 int Arreglo[Tamano] = {0, 0};
 // El Arreglo se ha inicializado a 0
 
 cout <<"\nEste programa recibe una serie de %d numeros enteros" << Tamano;
 cout <<" y los ordena por medio del algoritmo de ordenacion burbuja. "<< endl; 

 /*Se llena el arreglo mediante un llamado a la funcion Recibe*/
 Recibe(Arreglo);

 /*Se imprime el arreglo con las entradas en el orden original */
 cout <<"\nEsta es el orden en que se introdujeron los elementos: " <<endl;
 Imprime(Arreglo);

 /*Se ordena el arreglo mediante una llamada a la funcion Burbuja*/
 Burbuja(Arreglo);

 /*Se imprime el arreglo ordenado */
 cout <<"\nEste es el orden despues de el ordenamiento burbuja. " <<endl;
 Imprime(Arreglo);

 return 0;
 }           // Cierra main


 //////////////////////////////////////////////////
 //FUNCION IMPRIME 
 /////////////////////////////////////////////////
 
 void Imprime( int A[] )
 {     // Abre la funcion Imprime
 
 for ( int j = 0; j < Tamano; j++ )
 {      // Abre for
 cout << "\t" << A[j]; 

 if ( 0 == j + 1 % 10)
 cout <<endl <<endl;

 }      // Cierra for

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

 ////////////////////////////////////////////////////////////////////////////
 //FUNCION RECIBE
 //////////////////////////////////////////////////////////////////////////
 

 void Recibe( int B[] )
 {         // Abre funcion Recibe
 
 for ( int i = 0; i < Tamano; i++ )
 {      // Abre for
 cout << "\nIntroduzca el elemento " << i + 1 << " del arreglo: " << endl;
 cin >> B[i];
 }
 }         // Cierra funcion Recibe



 ///////////////////////////////////////////////
 //FUNCION BURBUJA
 /////////////////////////////////////////////////
 

  void Burbuja( int C[])
 {                 // Abre funcion Burbuja

 int temporal;

 for ( int m = 0; m < Tamano - 1; m++ )
 for ( int n = 0; n <= Tamano - 1; n++ )
 {    // Abre for
     
 if ( C[n] > C[n + 1] )
 {    // Abre if
 temporal = C[n]; 
 C[n] = C[n + 1];
 C[n + 1] = temporal;

 }    // Cierra if 
 }         //Cierra for
 }                 // Cierra funcion Burbuja

Deitel_Java_6.24 (Números perfectos en Java)

6.24 Se dice que un número es un número perfecto si sus factores, incluyendo 1 (pero no el número entero), al sumarse dan como resultado el número entero. Por ejemplo, 6 es un número perfecto, ya que  6 = 1 + 2 + 3. Escriba un método llamado Perfecto que determine si el parámetro número es un número perfecto. Use este método en una aplicación que determine y muestre todos los números perfectos entre 1 y 1000. Imprima los factores de cada número perfecto para confirmar que el número sea realmente perfecto. Ponga a prueba el poder de su computadora, evaluando números más grandes que 1000. Muestre los resultados.

Este problema también aparece resuelto en C++ en Deitel_C++_3.29.  En lugar de establecer 1000 como límite superior, se pide al usuario que lo introduzca. Para 10000 la salida es la siguiente:
Este programa imprime los numeros perfectos entre                                                               
 1 y un numero dado.                                                                                            
                                                                                                                
Por favor introduzca un entero positivo:                                                                        
10000                                                                                                           
6 =       1       2       3                                                                                     
                                                                                                                
28 =      1       2       4       7      14

496 =     1       2       4       8      16      31      62     124     248

8128 =    1       2       4       8      16      32      64     127     254     508     1016    2032    4064


El siguiente código debe guardarse con el nombre UsaDeitel_6_24.java
 
 import java.util.Scanner;

 public class UsaDeitel_6_24

 {        // Abre clase UsaDeitel_6_24

 public static void main(String args[])

 {         // Abre main

 Scanner entrada = new Scanner(System.in);
 int numero;
 Deitel_6_24 miObjeto = new Deitel_6_24();

 System.out.println("\nEste programa imprime los numeros perfectos entre");
 System.out.println(" 1 y un numero dado. ");

 do
 {         // Abre do
 System.out.println("\nPor favor introduzca un entero positivo: ");
 numero = entrada.nextInt();
 } while ( 0 > numero );      // Cierra do

 miObjeto.Perfecto(numero);

 }         // Cierra main
 }        // Cierra clase UsaDeitel_6_24

El siguiente código debe guardarse con el nombre Deitel_6_24.java

 public class Deitel_6_24

 {     // Abre Deitel_6_24


 //////////////////////////////////////////
 //METODO PERFECTO
 /////////////////////////////////////////
 public void Perfecto( int N )

 /* El metodo Perfecto recibe el limite superior
    es decir el numero hasta el que debe buscar perfectos.
    */
 {           // Abre metodo perfecto
 
 int cuenta = 0; 

 // La variable cuenta se utiliza para ir sumando los factores
 // del numero j, al final se verifica la condicion de que esa
 // suma sea igual al numero j. Si es asi, solo si es asi, se
 // manda a imprimir el numero. Esto porque de otra manera se
 // tendria que ir almacenando cada vez los factores, pero no 
 // se tiene a priori el numero, asi que no se sabe cuantas 
 // variables hay que declarar. Por lo tanto he decidido 
 // usar otro metodo para imprimir el numero que resulte perfecto.
 

 for ( int j = 1; j <= N; j++ ) 
 {       // Abre for

 cuenta = 0;
 // La variable cuenta se debe poner en cero cada vez que se 
 // analiza otro numero.
  
 for ( int i = 1; i <= j/2 ; i++ ) 

 // Solo hay que buscar los factores hasta j/2, porque despues
 // de ese numero ya no hay mas. 
 
 if( 0 == j % i )
 cuenta += i; 

 // Si la variable i es un  factor, se suma
 
 if ( cuenta == j )
 // Si la suma de los factores es igual al numero, entonces
 
 {      // ABre if
 Imprime(j);
  // se imprime
 }  // Cierra if
 }      // Cierra for
 }           // Cierra metodo perfecto


 //////////////////////////////////////
 //METODO IMPRIME
 //////////////////////////////////////
   
 public void Imprime( int x )
 
 // Esta funcion primero imprime el numero 
 {           // Abre Imprime
  
 System.out.printf("%d = ", x);
  
 for ( int s = 1; s <= x/2; s++ )
 {     // Abre for
 if ( 0 == x%s )
 System.out.printf("\t%3d", s);
 // y despues imprime los factores
 }     // Cierra for

 System.out.println("\n");

 }           // Cierra Imprime     
 
 }     // Cierra Deitel_6_24

jueves, 23 de junio de 2011

Deitel_Java_6.23 (Calcular el Menor de Tres Números en Java)

6.23 Escriba un metodo llamado Minimo que devuelva el menor de tres números de punto flotante. Use el método Math.min para implementar Minino. Incorpore el método en una aplicación que reciba como entrada tres valores por parte del usuario, determine el valore del menor y muestre el resultado.

El siguiente código debe guardarse con el nombre UsaDeitel_6_23.java
 import java.util.Scanner;

 public class UsaDeitel_6_23

 {     // Abre clase UsaDeitel_6_23

  public static void main(String args[])

  {         // Abre main

  Scanner entrada = new Scanner(System.in);
  double a;
  double b;
  double c;
  double minimo;
  Deitel_6_23 miObjeto = new Deitel_6_23();


  System.out.print("\nEste programa recibe tres numeros flotantes y ");
  System.out.print(" devuelve el mas chico.\n");

  System.out.print("\nIntroduzca tres numeros de punto flotante: \n");
  a = entrada.nextDouble();
  b = entrada.nextDouble();
  c = entrada.nextDouble();

  System.out.printf("\nEl menor de los numeros es: %.2f\n", miObjeto.Minimo(a,b,c)); 
  }   // Cierra main
 }        // Cierra clase UsaDeitel_6_23

El siguiente código debe guardarse con el nombre Deitel_6_23.java
 public class Deitel_6_23

 { // Abre clase Deitel_6_23

  public double Minimo( double x, double y, double z )
  
  {      // Abre metodo Minimo

  return Math.min( x, Math.min( y, z ) );

  }      // Cierra metodo Minimo
 } // Cierrra clase Deitel_6_23

Related Posts Plugin for WordPress, Blogger...