Los tipos básicos

En todos los lenguajes de programación hay que manejar tipos de datos. Puede que en algunos lenguajes el uso sea más explícito que en otros (por ejemplo, en Pascal hay que declararlos y en Python no), pero está claro que aún así el programador tiene que saber que tipo de datos está manejando en cada momento.

Como en la vida real, no es correcto mezclar unos tipos con otros. Por ejemplo, no es correcto mezclas las operaciones que puedes hacer con la fruta que las operaciones que puedes hacer con los automóviles… son dos cosas muy distintas. Aún hay cosas que puedes hacer que son similares como moverlas, comprarlas, etc, pero hay algunos principios que las diferencian, que son las operaciones que puedes hacer con uno que no puedes hacer con otro. Así por ejemplo, es normal comer fruta, pero no lo es tanto comer coches. Tampoco es normal conducir naranjas. ;-)

De la misma manera, en cualquier lenguaje, no es recomendable mezclar números con cadenas de caracteres (strings), con clases, etc, a menos que se quiera convertir de uno a otro. Aún así, Pascal permite esas mezclas, siempre y cuando definas la forma exacta en que pueden ser realizadas (esto es bastante avanzado, y se tratará en el apartado de Object Pascal sobre polimorfismo y sobrecarga de operadores).

Algunos lenguajes como Python, Perl, Ruby y Lisp, son más flexibles a la hora de mezclar tipos. Pero ello trae como consecuencia errores inesperados en tiempo de ejecución, las dichosas "excepciones". No obstante, y a pesar de esa dificultad inicial, saber y controlar que tipos de datos usas en cada momento te hará un mejor programador, y a la larga, no solo reportará en programas con menos errores y más rápidos, sino también en mejores programas porque sabes mejor que estás haciendo.

Los tipos numéricos

En Pascal existen varios tipos de números, con diferentes tamaños (espacio que ocupan en memoria), y diferentes capacidades (el número máximo y mínimo y la precisión que pueden manejar). Estos son:

Tipo Rango Bits Precisión
Shortint -128..127 8 entero
Smallint -32768..32767 16 entero
Longint -2147483648..2147483647 32 entero
Byte 0..255 8 entero
Word 0..65535 16 entero
Integer -2147483648..2147483647 32 entero
Cardinal 0..2147483647 32 entero
Real 2.9x10−39 .. 1.7x1038 48 36bits
Single 1.5x10−45 .. 3.4x1038 32 24bits
Double 5x10−324 .. 1.7x10308 64 48bits
Extended 3.4x10−4932 .. 1.1x104932 80 60bits
Comp -9223372036854775809..9223372036854775807 64 entero

Como puede comprobarse, hay un amplísimo rango de tipos númericos entre los que elegir. La cuestión es, precisamente, ¿cuál elegir?

La respuesta es: depende.

Normalmente se intentará elegir el tipo de dato más pequeño con el que sea suficiente hacer las operaciones para las que se esté programando en ese momento. Como normal general, un tipo numérico pequeño proporcionará más rápidez y ahorro de memoria. Sin embargo, y debido a como funcionan las actuales computadoras de 32 y 64 bits, es posible que el compilador decida utilizar 32 bits para un tipo de datos de 16 bits, sin que el programador se entere realmente. Esto es debido a que las operaciones con tipos de datos alienados en direciones equivalentes a las del procesador en uso suelen estar más optimizadas. No conviene abusar de los tipos de datos de mayor tamaño, como el Double y el Extended, que son capaces de almacenar números de dimensiones astronómicas pero a cambio de ser lentos y ocupar mucha memoria. Estos tipos son solamente recomendables para aplicaciones científicas que exijan manejar esos números y precisiones.

Recuerda: no uses un tipo grande de números a menos que lo necesites.

Los tipos de datos de precisión no entera, tales como Real, Single, etc, empiezan a perder precisión cuando se sobrepasa el valor de sus bits de mantisa (en la tabla está marcado en la columna Precisión). Así, como por ejemplo, en 24 bits solo se puede almacenar un número de 224, esto es, aproximadamente 16.7 millones, cuando se pasa de esos 16.7 millones la variable que contiene el número empieza a perder precisión y solo almacena un dato aproximado. Lo mismo sucede al sobrepasar cierto número de decimales. Cuanto mayor es la precisión, menos pérdidas de datos habrá. Recomiendo echar un vistazo al artículo en Wikipedia sobre coma flotante para comprender esto mejor.

Así mismo, hoy en día la velocidad de los tipos de coma flotante es tan rápida o casi como los tipos enteros. Sin embargo, usar tipos en coma flotante no está permitido en muchas partes del programa (por ejemplo, para indexar cadenas, como veremos más adelante), además de que, debido al redondeo, pueden producir serios bugs (errores) difíciles de detectar en algunos casos. Por lo tanto, se debe evitar su uso excepto para cuando realmente son útiles y de verdad se necesiten decimales.

Ejemplos práctico de uso de tipos numéricos

Es interesante comprobar hasta que punto se pueden mezclar unos datos numéricos con otros, y como los imprime writeln en la consola. Veamos el ejemplo de la lección anterior, retocado con nuevos tipos:

program leccion2;

var
  numero1 : Integer;
  numero2 : Byte;
  resultado : Double;

begin
  numero1 := 5;
  numero2 := 6;
  resultado := numero1 + numero2;
  writeln (resultado);
end.

Al ejecutarlo, tenemos esto:

1.10000000000000E+001

¿Por qué?

Porque la variable resultado es de tipo Double, con todos esos deciamales de precisión. El E+001 del final significa "por 10 elevado a más 1". Efectivamente, es lo mismo que 1.1x101 o lo que es lo mismo, simplemente 11.

Este ejemplo muestra bien como Pascal es capaz de convertir unos números en otros. Al fin y al cabo, se ha mezclado un Integer de 32bits con un Byte de solo 8bits, y ha puesto el resultado en un Double de 64bits en coma flotante.

Pero no siempre vamos a ser afortunados. Si el tipo de dato en donde quieres almacenar el resultado tiene un rango más pequeño que del que extraes el valor y es entero, entonces la conversión es, como es lógico, no correcta. Por ejemplo, ¿cómo almacenarías el valor 48484 en un byte? No se puede, un byte solo almacena números hasta 255, como se ha visto en la anterior tabla.

Prueba el mismo programa, modificado:

program leccion2;

var
  numero1 : Integer;
  numero2 : Real;
  resultado : Byte;

begin
  numero1 := 5;
  numero2 := 6;
  resultado := numero1 + numero2;
  writeln (resultado);
end.

Inevitablemente obtienes un error:

leccion2.pas(11,24) Error: Incompatible types: got "Real" expected "Byte"
leccion2.pas(15) Fatal: There were 1 errors compiling module, stopping

Recuerda: no mezcles tipos de datos a menos que estés absolutamente seguro que no habrá desbordamiento de rango.

Sin embargo, si eres libre de convertir un Double en un Single, ya que ambos son en coma flotante. Eso si, es muy posible que obtengas una "bonita" excepción de desbordamiento de operación, en tiempo de ejecución, si sobrepasas los límites de rango mostrados en la tabla anterior. Pruébalo para comprobarlo:

program leccion2;

var
  numero1 : Double;
  numero2 : Real;
  resultado : Single;

begin
  numero1 := 78e40;
  numero2 := 6;
  resultado := numero1 + numero2;
  writeln (resultado);
end.

El terrible resultado:

Runtime error 207 at $080480D0
  $080480D0  main,  line 12 of leccion2.pas
  $08061407

Recuerda: asegúrate de no pasarte de su rango u obtendrás una excepción que se presentará en el momento menos apropiado (generalmente cuando tu programa esté ya en la calle).

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License