miércoles, 28 de agosto de 2013

La instrucción goto y etiquetas

El lenguaje C proporciona la instrucción goto como una forma de transferir el control del programa. Por ejemplo considere el siguiente código

/*+++++++++++++++++++++++++++++++++++++++++++++++++
+ Este programa hace uso de la proposicion goto   +
**************************************************/

#include <stdio.h>

int main()

{ /* Abre main */
printf("\nEsta es la primera instruccion del programa.");

/* Se usa goto */
goto instruccion;

printf("\nEsta es la segunda instruccion del programa.");

instruccion:
printf("\nEsta es la tercera instruccion del programa.");
printf("\nEsta es la cuarta instruccion del programa.\n");
return 0;

} /* Cierra main */


Aquí se presenta una instrucción goto seguido del nombre de una etiqueta llamada instruccion. La función de goto es omitir la realización de todas las líneas que hay entre goto y la etiqueta. Una ejecución del programa es la siguiente:

hernandez@miMaquina ~/Programas $ ./a.out 

Esta es la primera instruccion del programa.
Esta es la tercera instruccion del programa.

Esta es la cuarta instruccion del programa.

Observe que la segunda línea printf no se imprime, debido al uso de la etiqueta goto. A partir de donde está la etiqueta, se reinicia la ejecución del programa en el orden en que aparecen las líneas de código. El uso de goto puede ser muy cómodo, pero es muy poco recomendado. La programación estructurada ha venido a ser sinónimo de "programación sin goto". En el pasado los ingenieros y desarrolladores se dieron cuenta de que los programas con goto eran más difíciles de mantener y depurar, debido a que no hay un orden en las instrucciones.

lunes, 22 de julio de 2013

Kernighan_Ritchie_2_7.c (Inversión de bits)

______________________________________________________________________________________________________________________
2.7 Escriba una función invert(x, p,n) que regresa x con los n bits que principian encla posición p invertidos (esto es, 1 cambiado a 0 y viceversa), dejando los otros sin cambio.
______________________________________________________________________________________________________________________
Solución:
Primero, hay que dejar claro de lo que se trata éste programa. Para ésto, vamos a suponer que se recibe como entrada el número 90, y se quiere invertir los 3 bits que empiezan a partir del tercero. Lo que éste programa hace, se muestra en la siguiente figura:
Éste programa invierte los bits en rojo.
Se observa que hay sustitución de 1 por 0 a partir del tercer bit (el primero es el 0), por lo cual, el número se transforma en 42.

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *                                                                  + 
 * Este programa recibe un entero sin signo e  invierte los n bits  + 
 * de dicho entero a   partir de la posicion p.                     +
 *                                                                  + 
 * Recibe x, que en binario es:                                     + 
 *                                                                  + 
 * |x|x|x|x|x|x|x|x|                                                + 
 * en donde x es 1 o 0                                              + 
 *                                                                  + 
 * tambien se recibe p (la posicion a partir de la cual se invertiran
 * los bits)  y n, el numero de bits a invertir. Por ejemplo, si se *
 * recibe x = 30, n = 2, p = 2.                                     *
 *             p                                                    *
 *   30 = |1|1|1|1|0|                                               * 
 *           2 1                                                    *
 *           n                                                      *
 *                                                                  *
 * Este programa inviert (cambia 1 por 0 y viceversa) los n bits    *
 * desde p. (la cuenta es hacia la izquierda, el primer bit es el 0 *
 * Así que para este caso el numero quedaria como:                  *
 *                                                                  *
 *        |1|0|0|1|0| = 18                                          *
 *                                                                  *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*******************************************************************+
 *                         ALGORITMO                                +
 * El problema se dividira en 2 partes principales                  +
 *                                                                  *
 * 1) Obtener el numero binario                                     *
 *                           p                                      *
 *    |0|0|0|0|...|0|x|x|...|x|0|...|0|                             *
 *                   p + n                                          *
 *                                                                  *
 *   donde los bits marcados con x son el complemento a 1 (inverso) *
 *   del numero entre 0 y p                                         *
 *                                                                  *
 * 2) Obtener el numero binario                                     *
 *                 p+n     n                                        *
 *    |x|x|x|...|x|0|0|...|0|x|....|x|                              *
 *                                                                  * 
 *    donde los bits marcados con x tienen el mismo valor que el    *
 *    numero original.                                              *
 *                                                                  *
 * El numero deseado se obtiene uniendo los que aparecen en 1) y 2) *
 * mediante el operador binario |                                   *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include <stdio.h>

///////////////////////////////////////////////////////////////////////////
//UNSIGNED
/////////////////////////////////////////////////////////////////////////// 
unsigned invert(unsigned x,int p,int n)

{ /* Abre invert */
return (((~(~0 << p + n) & (~0 << p)) & ~x) | ((( ~0 << p+n) | ~(~0 <<p)) & x) ); 
} /* Cierra invert */

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

int main()
{ /* Abre main */
unsigned numero;
int a, b;

printf("\nPor favor introduzca un entero sin signo: \n");
scanf("%d", &numero);

printf("\nPor favor introduzca el numero de bits a invertir: \n");
scanf("%d", &b);

printf("\nPor favor introduzca el bit a partir del cual se hara la inversion: \n");
scanf("%d", &a);

printf("\nEl numero, despues de invertir los %d bits a partir de la posicion ", a);
printf("%d es: %d\n", b, invert(numero, b,a));

return 0;
}  /* Cierra main*/

miércoles, 8 de mayo de 2013

Kernighan_Ritchie_2.6 (Desplazamiento y sustitución de bits)

_______________________________________________________________________________________
2.6 Escriba una función setbits(x,p,n,y) que regresa x con los n bits que principian en la posición p iguales a los n bits más a la derecha de y, dejando los otros bits sin cambio.
_______________________________________________________________________________________
Solución:
Lo primero, igual que en este ejemplo, es entender bien el enunciado. Para ésto, vamos a visualizar la representación binaria de un par de números enteros positivos, digamos el 51 y el 42. Para estos números bastan seis bits. Vamos a suponer que el número de bits del primer entero (51) que vamos a cambiar por otros tantos del segundo (42) serán 3 (la variable n de setbits), y que además queremos cambiarlos a partir de la posición 1 (variable p ). Es importante recordar que la posición extrema derecha de un byte es el bit 0. Una vez establecido ésto, lo que el programa quiere es lo que se muestra en la siguiente figura:
La función setbits elimina los bits rojos y los sustituye por los azules.
La función setbits intercambia los 3 bits a partir del primero en la representación binaria de 51, con los tres primeros de la representación binaria de 42. El resultado es el número 53. Una vez entendida esta gráfica, es muy fácil entender la línea única de la función:

return (~((~0 << p) & ~(~0 <<(p+n))) & x ) | (~(~0 << p+n) & (y << p));

Esta línea, a pesar de parecer muy poco intuitiva, surge de una análisis simple.
1) Hacer 0 los bits entre p y p+n en el primer número. Ésto se logra creando una máscara que contenga 1s en todas las entradas, salvo en dichos bits. Esa máscara se crea con (~((~0 << p) & ~(~0 <<(p+n))) & x ). 2) Correr los bits del segundo número hasta la posición p. Ésto es, (y << p). 3) Hacer 0 los bits del segundo número, salvo en los intervalos 0-p y p+n hasta el último. Esto se logra con la máscara (~(~0 << p+n) & (y << p)). 4) Usar el operador | para lograr la unión de los bits distintos de 0 en de ambos números.
En los comentarios del programa se presenta éste mismo procedimiento como explicación del algoritmo.


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
* Este programa recibe dos enteros sin signo. Regresa otro entero sin    *
* signo, el que se obtiene al cambiar n bits del primero, a partir de la *
* posicion p, con los n bits mas a la derecha del segundo.               *
*                                                                        *
* Lo que recibe: 4 enteros positivos.                                    *
* Lo que regresa: 1 entero positivo.                                     *
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*                               ALGORITMO:                               *
*Establecer a o los n bits del primer numero, a partir de la posicion p  *
*                                                                        *
*                                              p                         *
*      | x | x | x | x | x | x | 0 | 0 | ... | 0 | x | x | x |           *
*                              -     n   --------                        *
*                                                                        * 
*Mover los bits del segundo numero p posiciones a la izquierda           *
*                                                                        *
*Establecer a 0 todos los bits (antes de la posicion p y despues de la n)*
*del segundo numero                                                      *
*                                                                        *
*                                  n             p                       *
*      | 0 | 0 | 0 | 0 | ... | 0 | x | x | ... | x | 0 | 0 | 0 |         *
*                                                                        *
*Con el operador o inclusivo | (puede ser el ^ o exclusivo) obtener el   *
*numero buscado.                                                         *
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include 

///////////////////////////////////////////////////////////////////////
//setbits
///////////////////////////////////////////////////////////////////////

unsigned setbits( unsigned x, int p, int n, unsigned y)
{ /* Abre setbits */
 return (~((~0 << p) & ~(~0 <<(p+n))) & x ) | (~(~0 << p+n) & (y << p));
} /*Cierra setbits */

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

int main()
{  /* Abre main */
unsigned numero1, numero2;
int a, b;

printf("\nIntroduzca un entero sin signo: ");
scanf("%d", &numero1);

printf("\nIntroduzca un segundo entero sin signo: ");
scanf("%d", &numero2);

printf("\nIntroduzca el numero de bits a cambiar: ");
scanf("%d", &a);

printf("\nIntroduzca el bit a partir del cual se hara el cambio: ");
scanf("%d", &b);

printf("\nEl numero resultante es: %d\n", setbits(numero1, b, a, numero2));  

return 0; 
}  /* Cierra main */

ÉSte programa no tiene la precaución de verificar que los valores sean válidos. Por ejemplo, se podría introducir un valor de p mayor que el número total de bits. Ésto se puede evitar colocando algunos condicionales en la función main. No he querido colocarlos para no complicar el código. Es fácil hacerlo.
Aquí una ejecución, usando los números presentados anteriormente.

[hernandez@localhost Programas]$ ./a.out 

Introduzca un entero sin signo: 51

Introduzca un segundo entero sin signo: 42

Introduzca el numero de bits a cambiar: 3

Introduzca el bit a partir del cual se hara el cambio: 1

El numero resultante es: 53

__________________________________________________________________________________________
Esta entrada es parte de los problemas resueltos del libro El Lenguaje de Programación C de B. Kernighan y D. Ritchie
Entrada Anterior

Un ejemplo usando operadores para manejo de bits

Éste programa usa la función getbits (sección 2.9 de El Lenguaje de Programación C, de Kernighan y Ritchie). La razón para ponerlo aquí es que no es claro a primera vista, al menos para mí, lo que esa función hace. En la sección 2.9 se estudian los operadores binarios y getbits hace uso de &, el and de bits; <<, corrimiento a la izquierda; >>, corrimiento a la derecha y ~, complemento a uno, para hacer lo siguiente:
"regresa el campo de n bits de x (ajustado a la derecha) que principia en la posición p. Se supone que la posición del bit 0 está en el borde derecho y que n y p son valores positivos adecuados. Por ejemplo, getbits(x,4,3) regresa los tres bits que están en la posición 4, 3 y 2 ajustados a la derecha."

No soy el único que encuentra difícil la redacción (la original, en inglés) del libro de Kernighan y Ritchie. He encontrado varias páginas y foros en los que la gente se pregunta qué quisieron decir en tal o caul parte. Afortunadamente, aquí se puede entender sin ambigûedades.
Vamos a suponer que las variables son éstas: x = 179, p = 4 y n = 3. Para hacer ésto más fácil, la representación binaria de 179 es la siguiente:

Representación binaria de 179, en 10 bits.
Lo que hace nuestra función es mostrar dejar únicamente los 3 bits que comienzan a partir de la posición 4 (la posición extrema derecha es la 0). Éstos bits son 1 0 0, y deben aparecer corridos hacia la derecha. Todos los demás bits deben estar establecidos en 0.
El número 179 después de aplicar getbits.
El corazón del programa es, desde luego, la instrucción

return ((x >> (p+1-n)) & ~(~0 << n));

Ésta línea se divide en dos partes, separadas por el operador &. La instrucción x >> (p+1-n) corre hacia la derecha (4+1-3 = 2) bits. Esto es, se eliminan los bits 0 y 1 (ambos con 1), que deja el número binario 0000101100.
~(~0 << n) crea una máscara de bits. ~0 genera el binario 1111111111 y ~0 << n, con n = 3, corre hacia la izquierda el primer bit y llena los espacios con 0. Se produce entonces el número binario 1111111000. Finalmente, ~(~0 << n) crea el binario 0000000111. Esta es la máscara. Aplicando el operador & a 0000101100 y 0000000111 produce 0000000100. Este número es 4. Es precisamente lo que se obtiene al ejecutar el programa
/*++++++++++++++++++++++++++++++++++++++++++++
 * "regresa el campo de n bits de x (ajustado *
 * a la derecha) que principia en la posicion *
 * p. Se supone que la posicion del bit 0     *
 * esta en el borde derecho y que n y p son   *
 * valores positivos adecuados" Kernighan-    *
 * Ritchie                                    *
 *+++++++++++++++++++++++++++++++++++++++++++*/
#include 

///////////////////////////////////////
// FUNCION GETBITS
// ////////////////////////////////////

unsigned getbits(unsigned x, int p, int n)
{ /* Abre getbits*/
 
return ((x >> (p+1-n)) & ~(~0 << n));

} /*Cierra getbits*/

////////////////////////////////////////
//FUNCION MAIN
////////////////////////////////////////

int main()
{ /* Abre main*/

unsigned numero;
int a, b;

printf("\nIntroduzca un entero sin signo: ");
scanf("%d", &numero);

printf("\nIntroduzca el numero de bits a mostrar: ");
scanf("%d", &b);

printf("\nIntroduzca el numero de bit a partir del cual se mostraran: ");
scanf("%d", &a);

printf("El numero es: %d\n", getbits(numero,a,b));

return 0;
}/*Cierra main*/
Aquí la ejecución

[hernandez@localhost Programas]$ ./a.out 

Introduzca un entero sin signo: 179

Introduzca el numero de bits a mostrar: 3

Introduzca el numero de bit a partir del cual se mostraran: 4
El numero es: 4

jueves, 2 de mayo de 2013

De decimal a octal con una función recursiva

Éste programa es una consecuencia natural de la entrada anterior. Es tan simple como cambiar 2 por 8. En realidad, como puede verse, éste procedimiento sirve para convertir de decimal a cualquier base posicional entre 2 y 9. También es posible usarlo para una conversión a sistema hexadecimal.

#include <stdio.h>

/*////////////////////////////////////
 * Funcion Octal                     *
 *///////////////////////////////////*/

void Octal( int x)

{  /* Abre Octal*/
if ( x != 0 )
{ /* Abre if*/
Octal(x/8);

printf("%d\t", x%8);
} /*Cierra if */

else;
 /*printf("0\n");*/

}  /*Cierra Octal*/

/****************************************
 * main                                 *
 ***************************************/
int main()

{  /*Abre main */
 int num; 

 printf("\nIntroduzca un numero entero: ");
 scanf("%d", &num);

 Octal(num);
 printf("\n");

 return 0;
}  /*Cierra main */


Y aquí una ejecución, con el número 100 como entrada

[hernandez@localhost Programas]$ ./a.out 

Introduzca un numero entero: 100                                                     
1       4       4                   


miércoles, 1 de mayo de 2013

De decimal a binario con una función recursiva

Tengo una versión de éste programa que es bastante más complicada, pero por mucho tiempo recordé que lo había visto resuelto usando recursión. Ahora he pensado algunas formas de hacerlo, por ejemplo ésta:
Supongamos que tenemos el número 41, y que queremos convertirlo de su notación decimal a binario.
41 En binario  = 1 0 0 0 0 0 + (41 - 32) En binario

                                   9 En binario = 1 0 0 0 +  (9 - 8) En binario

                                                                1 En binario = 1.
El problema se va reduciendo cada vez por medio de llamadas a sí mismo con argumentos más simples. Al final sólo es necesario sumar las representaciones binarias de 32 + 8 + 1. Sin embargo no es ésto lo que yo quiero aquí. Además, sumar será en éste caso más complicado que la propia conversión. Por lo tanto descarté ésta posibilidad.
Otra forma es sugerida por el siguiente proceso, que puede encontrarse por ejemplo en el libro de Diseño Digital, de Morris Mano:
Número          División       Residuo          Binario
  41/2     =       40/2    +     1/2              1
  
  20/2     =       20/2    +      0               0

  10/2     =       10/2    +      0               0
 
   5/2     =        4/2    +     1/2              1
 
   2/2     =        2/2    +      0               0

   1/2     =          0    +     1/2              1
Éste algoritmo es fácilmente programable usando el operador %. Sin embargo, tiene el gran inconveniente de que los dígitos se imprimen en el orden inverso, como puede verse al ejecutar el siguiente código

#include <stdio.h>

/*////////////////////////////////////
 * Funcion Binario                   *
 *///////////////////////////////////*/

void Binario( int x)

{  /* Abre binario*/
if ( x != 0 )
{ /* Abre if*/
printf("%d\t", x%2);

Binario(x/2);

} /*Cierra if */

else;
 /*printf("0\n");*/

}  /*Cierra binario*/

/****************************************
 * main                                 *
 ***************************************/
int main()

{  /*Abre main */
 int num; 

 printf("\nIntroduzca un numero entero: ");
 scanf("%d", &num);

 Binario(num);

 return 0;
}  /*Cierra main */


La ejecución es la siguiente

[hernandez@localhost Programas]$ ./a.out 

Introduzca un numero entero: 41
1       0       0       1       0       1  

De nuevo el problema es que se está imprimiendo el número al revés. Ésto es grave, porque el código es muy bueno, y cualquier intento por corregir el defecto, requiere algoritmos más complicados que la propia conversión.
Sin embargo, después de pensarle, la solución es muy simple. En la función Binario, basta con cambiar el orden de los dos únicos enunciados. Primero hay que hacer una llamada a Binario, y ésto llevará la ejecución hasta el final, hasta el caso más simple, y el control se regresará desde el último caso, imprimiendo los dígitos binarios en el orden inverso. El programa correcto es el siguiente:

#include <stdio.h>

/*////////////////////////////////////
 * Funcion Binario                   *
 *///////////////////////////////////*/

void Binario( int x)

{  /* Abre binario*/
if ( x != 0 )
{ /* Abre if*/
Binario(x/2);

printf("%d\t", x%2);
} /*Cierra if */

else;
 /*printf("0\n");*/

}  /*Cierra binario*/

/****************************************
 * main                                 *
 ***************************************/
int main()

{  /*Abre main */
 int num; 

 printf("\nIntroduzca un numero entero: ");
 scanf("%d", &num);

 Binario(num);

 return 0;
}  /*Cierra main */


La ejecución,
[hernandez@localhost Programas]$ ./a.out 

Introduzca un numero entero: 41
1       0       1       0       0       1
Comopuede verse, son muy pocas las líneas que se requieren para hacer la conversión de binario a decimal usando la recursión, y es un cambio mínimo el que hace esta diferencia.

lunes, 29 de abril de 2013

Factoriales y Números de Fibonacci en java.

El siguiente programa en java recibe un número entero positivo. Si el número es par, se imprime el factorial, de lo contrario se imprime el número de fibonacci correspondiente a dicho entero. En los comentarios se esbozan los algoritmos.
Éste archivo debe guardarse con el nombre Main.

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* Programa que recibe un entero positivo y verifica si es par +
* o impar                                                     *
* Si es par                                                   *
*   Se calcula e imprime el factorial del numero              *
* Si es impar                                                 *
*   Se calcula e imprime los primeros n numeros de fibonacci  *
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

import java.util.Scanner;

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

int n = 0; // Esta variable almacenara el numero
Scanner entrada = new Scanner(System.in);

while ( 0 >= n )
 // con este condicional while se garantiza que el usuario introduzca numeros positivos.
{  // Abre while
System.out.print("\nPor favor introduzca un numero entero. Si el numero es par ");
System.out.print("se imprimira el factorial, de lo contrario, se imprimiran los primeros n terminos ");
System.out.println("de la serie de Fibonacci. "); 
n = entrada.nextInt();

}  // Cierra while

if ( 0 == n%2 )  // Si el numero es par
System.out.printf("\nEl factorial del numero es: %d\n\n", factorial(n));
else  // Si el numero es impar
fibonacci(n);

}  // Cierra main

///////////////////////////////
//Metodo fibonacci
//////////////////////////////

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *                                                                             *
 *                              ALGORITMO                                      *
 *                              _________                                      *
 *                                                                             *
 * El primer numero de fibonacci (fib1) es 0                                   *
 * El segundo numero de Fibonacci (fib2) es 1                                  *
 *                                                                             *
 * Si el usuario introduce 1 o 2, entonces es necesario desplegar f1 o f2      *
 * Si el usuario introduce un entero positivo mayor que 2, entonces            *
 *     desde 2 hasta n (el numero introducido)                                 *
 *     fibn = fib1 + fib2                                                      *
 *     temp =  fib2                                                            *
 *     fib2 = fibn                                                             *
 *     fib1 = temp                                                             *
 *                                                                             *
 * Imprimir el valor de fibn                                                   * 
 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

public static void fibonacci( int x)
{  // Abre Metodo fibonacci

int fib1 = 0;
int fib2 = 1;
int fibn;

if (1 != x)
{  // Abre if
System.out.printf("\nEl primer numero de Fibonacci es: %d", fib1);
System.out.printf("\nEl segundo numero de Fibonacci es: %d", fib2);

for ( int i = 3; i <= x; i++ )
{  // Abre for
fibn = fib2 + fib1;
fib1 = fib2;
fib2 = fibn;

System.out.printf("\nEl numero de Fibonacci %d es %d", i, fibn);

}  // Cierra for  
System.out.println();
}  // Cierra if
else
System.out.println("\nEl primer numero de Fibonacci es: 0");


}  // Cierra Metodo fibonacci


/////////////////////////////////////////////////////
//Metodo factorial
/////////////////////////////////////////////////////

/*++++++++++++++++++++++++++++++++++++++++++++++++++*
*                                                   *
* fact = 1;                                         *
* Desde i = 1 hasta i = n                           *
*    fact = fact * i;                               *
*    i  =  i + 1;                                   *
*+++++++++++++++++++++++++++++++++++++++++++++++++++*/

public static int factorial( int n)
{  // Abre metodo factorial
int i; // La variable i servira como contador
int fact = 1; // Esta variable almacena el factorial

for ( i = 1; i <= n; i++ )
fact *= i;

return fact; // El valor de retorno es el factorial
}  // Cierra metodo factorial

}  // Cierra clase Main

Abajo aparece un par de ejecuciones del programa, una con un número par y otra con un número impar.

[hernandez@localhost Programas]$ java Main

Por favor introduzca un numero entero. Si el numero es par, se imprimira el factorial, de lo contrario, se imprimiran los primeros n terminos de la serie de Fibonacci. 
4

El factorial del numero es: 24

[hernandez@localhost Programas]$ java Main

Por favor introduzca un numero entero. Si el numero es par se imprimira el factorial, de lo contrario, se imprimiran los primeros n terminos de la serie de Fibonacci. 
7

El primer numero de Fibonacci es: 0
El segundo numero de Fibonacci es: 1
El numero de Fibonacci 3 es 1
El numero de Fibonacci 4 es 2
El numero de Fibonacci 5 es 3
El numero de Fibonacci 6 es 5
El numero de Fibonacci 7 es 8

viernes, 26 de abril de 2013

El Operador ~ de bits

El operador ~ de bits, también llamado operador de complemento a uno, actúa sobre tipos enteros (char, int, shor, long) a nivel de bits. Lo que hace es cambiar 0 por 1 y viceversa. Por ejemplo, si se tiene el la constante int x = 47 en una representación binaria de 6 bits, 101111, la instrucción ~x da como resultado el número 010000. Hay que tener cuidado antes de apresurarnos a decir cual será el resultado aplicando éste operador en un programa en C. El punto importante aquí es que si nosotros imprimimos el valor actual de x, mediante una instrucción printf, obtendremos -48.

La acción del operador complemento a uno
Sea el siguiente programa


/*+++++++++++++++++++++++++++++++++++++++++++++
 * Este programa cambia un numero sin sigo a  +
 * su complemento a uno a nivel de bits       +
 * ++++++++++++++++++++++++++++++++++++++++++*/

#include 

int main()
{  /* Abre main*/
unsigned contador;
unsigned x;
unsigned temporal;

printf("\nIntroduzca un número: ");
scanf("%d", &x);

temporal = ~x;

printf("\nEl complemento a uno de %d es: %d\n", x, temporal);

printf("\nEl valor final de x: %d\n", x);

return 0;
}  /* Cierra main*/

Una ejecución con 47 como entrada es la siguiente:


Introduzca un número: 47

El complemento a uno de 47 es: -48

El valor final de x: 47

Si las computadoras representaran los enteros con signo mediante el complemento a 1, el número al aplicar ~x sería -47, sin embargo, las computadoras almacenan los enteros con signo mediante la representación en complemento a dos. En ésta entrada hay más información al respecto.

miércoles, 24 de abril de 2013

El operador & de bits

El operador &, llamado AND de bits, compara dos números de tipo entero (int, short, long, char) bit por bit, dando por resultado un tercer número, que se forma al colocar un 0 ó 1 en el bit correspondiente a la comparación realizada de acuerdo con la siguiente regla: si los dos bits son iguales a 1, entonces se obtiene 1, de otra forma se obtiene un 0. Sean, por ejemplo, los números 19 y 25, que en representación binaria de 5 bits se escriben 19 = 1 0 0 1 1, 25 = 1 1 0 0 1. Si se realiza la comparación, se verá que los bits de la derecha son los dos iguales a 1, por lo tanto el número resultante tendrá un 1 en el bit de la extrema derecha. De manera similar, el segundo bit de 19 tiene un 1, en tanto que el de 25 tiene un 0, el resultado, por lo tanto, es 0. La comparación completa aparece en la figura de abajo.

El operador lógico & de bits.
El operador & también es utilizado para hacer referencia a una localidad de memoria,por ejemplo en la función scanf. Los usuarios de C++, que utilizan un lenguaje orientado a objetos, le llamarían a ésto una sobrecarga: el mismo operador se utiliza en situaciones distintas para realizar distintas tareas. La razón por la cual & no puede operar sobre tipos flotantes es porque la representación de números enteros es distinta a la de los tipos float. El programa que aparece abajo hace uso de el operador de bits &.

/*+++++++++++++++++++++++++++++++++++++++*
*Este programa recibe un par de numeros  *
*e imprime el resultado de aplicarles el *
*operador binario &                      *
*+++++++++++++++++++++++++++++++++++++++*/

#include 

int main()
{   /*Abre main*/
 int x; 
 int y;
 
 printf("\nEste programa hace uso del operador binario &\n");
 printf("\nIntroduzca un entero: ");
 scanf("%d", &x);
 printf("\nIntroduzca un segundo entero: ");
 scanf("%d", &y);

 printf("\n%d & %d = %d\n", x, y, x&y);

 return 0;
}   /*Cierra main*/

Una ejecución del programa, co los números 19 y 25 es:

Este programa hace uso del operador binario &                                        
                                                                                     
Introduzca un entero: 19                                                             
                                                                                     
Introduzca un segundo entero: 25                                                     
                                                                                     
19 & 25 = 17  

En ocasiones es conveniente fijar una constante entera mediante un número binario, por ejemplo para crear una máscara de bits. La forma de hacer ésto en C es escribiendo la constante en sistema de numeración octal o en hexadecimal. Toda constante que es precedida por un 0, como 0177, es tomada como una cantidad octal (127 en éste caso); en tanto que las cantidades precedidas de 0x ó 0X, como 0x7F (también igual al 127 decimal) son cantidades hexadecimales. En particular el número 0x7F se representa, en notación binaria, como 01111111 por lo cual, una instrucción como x & 0x7F, hará 0 todos los bits de x, salvo los primeros 7 de la derecha.

miércoles, 13 de febrero de 2013

Dale-Weems _3_1 (El volumen de un cono en C++)

A continuación presento unos ejercicios del libro de programación de Nale Cale y Chip Weems, cuarta edición: Programación y resolución de problemas con C++, que aparecerán en la etiqueta Dale - Weems.
_______________________________________________________________________________________
3.1 Escriba un programa en C++ que calcule y produzca elvolumen de un cono, dados el diámetro de su base y su altura. La fórmula para calcular el volumen del cono es:
(1/3)*Radio*Radio*Altura
Asegúrese de usar el formato y comentarios apropiados en su código. La salida debe ser etiquetada de manera clara.
_______________________________________________________________________________________
Solución:

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*  Este programa calcula e imprime el volumen de un cono  +
*                                                         +  
*  Lo que recibe:                                         +
*   - Diametro de la base                                 +
*   - Altura                                              +
*                                                         +
*  Lo que devuelve:                                       +
*   - El volumen                                          +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *                      ALGORITMO                         +
 *                                                        +
 * Recibir el diametro de la base.                        +
 * Recibir la altura                                      +
 *                                                        +
 * radio = diametro/2                                     +
 * volumen = (1/3)radio*radio*altura                      +
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include<iostream>
using namespace::std;

int main()

{  /* Abre main*/
/* Se declaran los datos */
float diametro, radio, altura, volumen;

/* Se reciben los datos */
cout <<"\nEste programa calcula el volumen de un cono."<<endl;
cout<<"Por favor introduzca el diametro de la base: " << endl;
cin >> diametro;

cout<<"Por favor introduzca la altura del cono: " << endl;
cin >> altura;

/*Se calcula el volumen */
radio = diametro/2;
volumen = ((float)1/3)*radio*radio*altura;

cout <<"\nEl radio del cono es: " <<radio<< endl;
cout <<"\nLa altura del cono es: " <<altura<< endl;
/*Se imprime el resultado*/
cout <<"\nEl volumen del cono es: " <<volumen << endl;

return 0;
}  /* Cierra main*/

_______________________________________________________________________________________
Éste programa hace uso de la fórmula dada en el enunciado, y lo único en lo que hay que tener cuidado es en la sintaxis correcta.
La línea

volumen = ((float)1/3)*radio*radio*altura;

es importante. Aquí se hace una conversión explícita del numerador en la fracción 1/3. De no hacerse, la división de enteros se trunca a 0. Basta con convertir el numerador (o el denominador) para que la fracción sea un número flotante.
Aquí una ejecución del programa:

Este programa calcula el volumen de un cono.
Por favor introduzca el diametro de la base: 
3
Por favor introduzca la altura del cono: 
4

El radio del cono es: 1.5

La altura del cono es: 4

El volumen del cono es: 3

Related Posts Plugin for WordPress, Blogger...