Conceptos Fundamentales de C++: Codificación y Operaciones Básicas

Tabla de Contenidos

  • Códigos ASCII
  • Operaciones Booleanas
  • Y (AND)
  • O (OR)
  • O Exclusivo (XOR)
  • Negación (NOT)
  • Sistemas Numéricos
  • Números octales (base 8)
  • Números hexadecimales (base 16)
  • Representaciones binarias

Códigos ASCII

Es un conocimiento ampliamente extendido que los computadores solo pueden manejar internamente los dígitos 0 (ceros) y 1 (unos). Esto es cierto, y mediante secuencias de 0s y 1s, el computador puede expresar cualquier valor numérico como su traducción binaria, que es una operación matemática bastante sencilla (como se explica en el documento sobre bases numéricas).

No obstante, no existe una forma evidente de representar letras y otros caracteres no numéricos con 0s y 1s. Por ello, para lograr esto, los computadores utilizan tablas ASCII, que son tablas o listas que contienen todas las letras del alfabeto romano junto con algunos caracteres adicionales. En estas tablas, cada carácter siempre está representado por el mismo número ordinal. Por ejemplo, el código ASCII para la letra mayúscula "A" siempre se representa con el número ordinal 65, que es fácilmente representable usando 0s y 1s en binario: 65 expresado como número binario es 1000001.

La tabla ASCII estándar define 128 códigos de caracteres (del 0 al 127), de los cuales, los primeros 32 son códigos de control (no imprimibles), y los 96 códigos restantes son caracteres representables:

* 0 1 2 3 4 5 6 7 8 9 A B C D E F
0 NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI
1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2 ! " # $ % & ' ( ) * + , - . /
3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4 @ A B C D E F G H I J K L M N O
5 P Q R S T U V W X Y Z [ |] ^ _
6 ` a b c d e f g h i j k l m n o
7 p q r s t u v w x y z { } ~

* Este panel está organizado para facilitar su lectura en hexadecimal: los números de fila representan el primer dígito y los números de columna representan el segundo. Por ejemplo, el carácter "A" se encuentra en la fila 4 y columna 1, por lo que se representaría en hexadecimal como 0x41 (65).

Debido a que la mayoría de los sistemas actuales trabajan con bytes de 8 bits, que pueden representar 256 valores diferentes, además de los 128 códigos ASCII estándar, existen otros 128 conocidos como ASCII extendido, que dependen de la plataforma y la configuración regional. Por lo tanto, hay más de un conjunto de caracteres ASCII extendido.

Los dos conjuntos de caracteres ASCII extendido más utilizados son el conocido como OEM, que proviene del conjunto de caracteres incorporado por defecto en IBM-PC, y el otro es el ASCII extendido ANSI, utilizado por la mayoría de los sistemas operativos modernos.

El primero, el conjunto de caracteres OEM, es el utilizado por el hardware de la inmensa mayoría de las máquinas compatibles con PC, y también se usó bajo el antiguo sistema DOS. Incluye algunos signos extranjeros, caracteres marcados y elementos para representar paneles.

El conjunto de caracteres ANSI es un estándar que incorporan muchos sistemas, como Windows, algunas plataformas UNIX y muchas aplicaciones independientes. Incluye muchos más símbolos locales y letras marcadas para que pueda usarse sin necesidad de ser redefinido en muchos más idiomas:

--------------------------------------------------

Operaciones Booleanas

Un bit es la cantidad mínima de información que podemos imaginar, ya que solo almacena el valor 1 o 0, que representa SÍ o NO, activado o desactivado, verdadero o falso, etc... es decir: dos estados posibles, cada uno opuesto al otro, sin posibilidad de matices. Consideraremos que los dos valores posibles de un bit son 0 y 1.

Se pueden realizar varias operaciones con bits, ya sea en combinación con otros bits o por sí solas. Estas operaciones reciben el nombre de operaciones booleanas, una palabra que proviene del nombre de uno de los matemáticos que más contribuyó a este campo: George Boole (1815-1864).

Todas estas operaciones tienen un comportamiento establecido y todas pueden aplicarse a cualquier bit sin importar qué valor contengan (ya sea 0 o 1). A continuación se presenta una lista de las operaciones booleanas básicas y una tabla con el comportamiento de esa operación con cada combinación posible de bits.

Y (AND)

Esta operación se realiza entre dos bits, que llamaremos a y b. El resultado de aplicar esta operación Y es 1 si tanto a como b son iguales a 1, y 0 en todos los demás casos (es decir, si uno o ambos de las variables es 0).

Y (&)

a b a&b
0 0 0
0 1 0
1 0 0
1 1 1

O (OR)

Esta operación se realiza entre dos bits (a y b). El resultado es 1 si cualquiera de los dos bits es 1, o si ambos son 1. Si ninguno es igual a 1, el resultado es 0.

O (|)

a b a|b
0 0 0
0 1 1
1 0 1
1 1 1

O Exclusivo (XOR)

Esta operación se realiza entre dos bits (a y b). El resultado es 1 si cualquiera de los dos bits es 1, pero no en el caso de que ambos lo sean. Por lo tanto, si ninguno o ambos son iguales a 1, el resultado es 0.

O Exclusivo (^)

a b a^b
0 0 0
0 1 1
1 0 1
1 1 0

Negación (NOT)

Esta operación se realiza sobre un solo bit. Su resultado es la inversión del valor actual del bit: si estaba establecido en 1 se convierte en 0, y si era 0 se convierte en 1:

Negación (~)

a ~a
0 1
1 0

Estas son las 4 operaciones booleanas básicas (Y, O, O Exclusivo y Negación). Combinando estas operaciones podemos obtener cualquier resultado posible de dos bits.

En C++, estos operadores pueden usarse con variables de cualquier tipo de dato entero; la operación booleana se realiza en todos los bits de cada variable involucrada. Por ejemplo, suponiendo dos variables: x e y, ambas de tipo unsigned char, donde x contiene 195 (11000011 en binario) e y contiene 87 (o 01010111 en binario). Si escribimos el siguiente código:

unsigned char x=195;
unsigned char y=87;
unsigned char resultado;
resultado=x&y;


Esto significa que realizamos una operación AND bit a bit entre x e y. La operación se realiza entre los bits de las dos variables que están en la misma posición: el bit más a la derecha de resultado contendrá el resultado de realizar la operación AND entre los bits más a la derecha de x e y:

La misma operación también se realiza entre los segundos bits de ambas variables, y el tercero, y así sucesivamente, hasta que la operación se realice entre todos los bits de ambas variables (cada uno solo con el mismo bit de la otra variable).

El valor binario final de resultado es 01000011, que es 67 en números decimales. Por lo tanto, 195&87 es igual a 67.

----------------------------------------------------------------------

Sistemas Numéricos

Desde niños, todos hemos usado decimales para expresar cantidades. Esta nomenclatura que nos parece tan lógica puede no parecerlo a un habitante de la Roma Clásica. Para ellos, cada símbolo que escribían para expresar un número siempre representaba el mismo valor:

I 1
II 2
III 3
IV 4
V 5


Todos los signos I siempre representan el valor 1 (uno) donde sea que se coloquen, y el signo V siempre representa un valor de 5 (cinco). Sin embargo, esto no ocurre en nuestro sistema decimal. Cuando escribimos el símbolo decimal 1, no siempre estamos hablando de un valor de uno (I en números romanos). Por ejemplo:

1 I
10 X
100 C


En estos casos, nuestro símbolo 1 no siempre tiene un valor de uno (o I en números romanos). Por ejemplo, en el segundo caso, el símbolo 1 representa un valor de diez (o X en romano) y en el tercero, 1 representa un valor de cien (o C).

Por ejemplo:

275 no es equivalente a 2+7+5, sino que podría descomponerse como 200+70+5:

200
+ 70
5
---
275


por lo tanto, el primer signo "2" es equivalente a 200 (2 x 100), el segundo signo "7" es equivalente a 70 (7 x 10) mientras que el último signo corresponde al valor 5 (5 x 1).

Esto se debe a que nuestro sistema es un sistema de numeración posicional. Por lo tanto, el valor de un dígito determiando depende de su posición dentro del número representado. Todo lo anterior puede representarse matemáticamente de una forma muy sencilla. Por ejemplo, para representar el valor 182736 podemos asumir que cada dígito es el producto de sí mismo multiplicado por 10 elevado a su posición como exponente, comenzando desde la derecha con 100, seguido con 101, 102, y así sucesivamente:

Números octales (base 8)

Al igual que nuestros "normales" números son base 10 (o radix 10) porque tenemos 10 dígitos diferentes (del 0 al 9):

0123456789


los números octales incluyen solo las representaciones para los valores del 0 al 7:

01234567


y, por lo tanto, su base matemática es 8. En C++ los números octales se denotan siempre comenzando con un dígito 0. Veamos cómo escribiríamos los primeros números en octal:

octal decimal
----- -------
0 0 (cero)
01 1 (uno)
02 2 (dos)
03 3 (tres)
04 4 (cuatro)
05 5 (cinco)
06 6 (seis)
07 7 (siete)
010 8 (ocho)
011 9 (nueve)
012 10 (diez)
013 11 (once)
014 12 (doce)
015 13 (trece)
016 14 (catorce)
017 15 (quince)
020 16 (dieciséis)
021 17 (diecisiete)


Así, por ejemplo, el número 17 (diecisiete, o XVII en romano) se expresa como 021 en número octal en C++. Podemos aplicar el mismo mecanismo que vimos anteriormente para los números decimales a los números octales simplemente considerando que su base es 8. Por ejemplo, tomando el número octal 071263:

por lo tanto el número octal 071263 se expresa como 29363 en números decimales.

Números hexadecimales (base 16)

Al igual que los números decimales tienen 10 dígitos diferentes para ser representados (0123456789) y los números octales tienen 8 (01234567), los números hexadecimales tienen 16 dígitos diferentes, que se representan con los números del 0 al 9 y las letras A, B, C, D, E y F, que juntos nos sirven para representar los 16 símbolos diferentes que necesitamos para expresar números base 16:

hexadecimal decimal
----------- -------
0 0 (cero)
0x1 1 (uno)
0x2 2 (dos)
0x3 3 (tres)
0x4 4 (cuatro)
0x5 5 (cinco)
0x6 6 (seis)
0x7 7 (siete)
0x8 8 (ocho)
0x9 9 (nueve)
0xA 10 (diez)
0xB 11 (once)
0xC 12 (doce)
0xD 13 (trece)
0xE 14 (catorce)
0xF 15 (quince)
0x10 16 (dieciséis)
0x11 17 (diecisiete)


En C++, los números hexadecimales van precedidos de 0x (cero, x).

Una vez más podemos usar el mismo método para traducir un número de una base a otra:

Representaciones binarias

Los números octales y hexadecimales tienen una ventaja considerable sobre nuestros números decimales en el mundo de los bits, y es que sus bases (8 y 16) son múltiplos perfectos de 2 (2³ y 2⁴, respectivamente), lo que nos permite hacer conversiones más fáciles de estas bases a binario que de números decimales (cuya base es 2x5). Por ejemplo, supongamos que queremos traducir la siguiente secuencia binaria a números de otras bases:

110011111010010100


Para traducirla a decimal necesitaríamos realizar una operación matemática similar a la que hemos usado anteriormente para convertir de hexadecimal u octal, lo que nos daría el número decimal 212628.

Sin embargo, para pasar esta secuencia a octal solo nos tomaría unos segundos e incluso los menos diestros en matemáticas pueden hacerlo simplemente viéndola: Como 8 es 2³, separaremos el valor binario en grupos de 3 números:

110 011 111 010 010 100


y ahora solo tenemos que traducir a radix octal cada grupo por separado:

110 011 111 010 010 100
6 3 7 2 2 4


dando como resultado el número 637224. Este mismo proceso puede realizarse inversamente para pasar de octal a binario. Para realizar la operación con números hexadecimales solo tenemos que realizar el mismo proceso pero separando el valor binario en grupos de 4 números, porque 16 = 2⁴:

11 0011 1110 1001 0100
3 3 E 9 4


Por lo tanto, la expresión binaria 110011111010010100 puede representarse en C++ como 212628 (decimal), como 0637224 (octal) o como 0x33e94 (hexadecimal).

El código hexadecimal es especialmente interesante en ciencias de la computación ya que actualmente, los computadores se basan en bytes compuestos por 8 bits binarios y por lo tanto cada byte corresponde con el rango que pueden representar 2 números hexadecimales. Por esa razón es tan frecuentemente utilizado para representar valores traducidos a o desde base binaria.

Etiquetas: C++ ASCII Booleanas binario Octal

Publicado el 7-18 03:32