Fundamentos de programación con Módula-2 (5)

 

Tema 2
Elementos Básicos de la
Programación Imperativa
 
 
 
En este tema se presenta un conjunto mínimo de elementos de un lenguaje de programación imperativo. Este conjunto se particulariza para el lenguaje Modula-2. Con los elementos presentados se podrán construir programas completos aunque con una estructura muy simple, ya que sólo pueden estar formados por una secuencia de sentencias. Para que estos primeros programas produzcan resultados, se introducen ya varios procedimientos de escritura simple.
 
El objetivo que trata de alcanzar este tema es permitir el desarrollo de programas completos desde el principio del curso. Estos programas se podrán realizar como prácticas con el computador de manera inmediata y directa.
 
 
2.1 Notación BNF
 
Un lenguaje de programación sigue unas reglas gramaticales similares a las de cualquier idioma humano, aunque más estrictas. Para la definición formal de dichas reglas sintácticas utilizaremos la notación BNF (Backus-Naur Form) basada en la descripción de cada elemento gramatical en función de otros más sencillos, según determinados esquemas o construcciones. Cada uno de estos esquemas se define mediante una regla de producción.
 
Estas reglas sobre cómo han de escribirse los elementos del lenguaje en forma de símbolos, que se denominan metasímbolos. Son los siguientes:
 
     ::=   Metasímbolo de definición. Indica que el elemento a su izquierda puede desarrollarse según el esquema de la derecha.
 
     |   Metasímbolo de alternativa. Indica que puede elegirse uno y sólo uno de los elementos separados por este metasímbolo.
 
     {}   Metasímbolos de repetición. Indican que los elementos incluidos dentro de ellos se pueden repetir cero o más veces.
 
     []   Metasímbolos de opción. Indican que los elementos incluidos dentro de ellos pueden ser utilizados o no.
 
     ()   Metasímbolos de agrupación. Agrupan los elementos incluidos en su interior.
 
Estos metasímbolos se escriben en el tipo de letra especial indiciado para distinguirlos de los paréntesis, corchetes, etc. que forman parte del lenguaje Modula-2. También se emplearán distintos estilos de letra para distinguir los elementos simbólicos siguientes:
 
     Elemento_no_terminal   Este estilo se emplea para escribir el nombre de un elemento gramatical que habrá de ser definido por alguna regla. Cualquier elemento a la izquierda del metasímbolo ::= será no terminal y aparecerá con este estilo.
 
     Elemento_terminal   Este estilo se emplea para representar los elementos que forman parte del lenguaje Modula-2, es decir, que constituyen el texto de un programa. Si aparecen en una regla deberán escribirse exactamente como se indica.
 
 
2.2 Valores y tipos
 
El computador, como máquina de tratamiento de información, manipula diferentes datos. Un dato es un elemento de información que puede tomar un valor entre varios posibles. Si un dato tiene siempre necesariamente un valor fijo, diremos que es una constante.
 
Los valores de los datos pueden ser de diferentes clases. En general un dato sólo puede tomar valores de una clase. Por ejemplo, la estatura de una persona no puede tomar el valor "Felipe", ni el nombre de una persona puede ser "175".
 
En programación a las distintas clases de valores se les denomina tipos. Un dato tiene asociado un tipo, que representa la clase de valores que puede tomar. Por ejemplo, son tipos diferentes:
 
  • Los números enteros
  • Los días de la semana
  • Los meses del año
  • Los títulos de libros
   …etc. …
 
Es importante destacar que el concepto de tipo es algo abstracto, e independiente de los símbolos concretos que se empleen para representar los valores. Por ejemplo, aunque podemos representar los meses del año mediante números enteros de 1 a 12, los meses no son números enteros, pues no tiene sentido, por ejemplo, sumar Enero (1) y Marzo (3) para obtener Abril (4).
 
Con más precisión se habla de tipos abstractos de datos, que identifican tanto el conjunto de valores que pueden tomar los datos de ese tipo como las operaciones significativas que pueden hacerse con dicho valores.
 
En la comunicación humana usamos habitualmente dos grandes clases de valores: los números y los textos. Los lenguajes de programación llevan incluidas formas de representación concretas de estas clases de valores, que se traducen en la existencia de tipos de datos predefinidos, ya incorporados al lenguaje, y que pueden usarse, en su caso, para representar también valores de otros nuevos tipos de datos definidos por el programador. Aunque en la práctica los números han de escribirse externamente en forma de texto para poder ser leídos por las personas, desde el punto de vista abstracto son valores de tipos diferentes a los de los caracteres que los representan.
 
 
2.3 Representación de valores constantes
 
Uno de los objetivos de los lenguajes de programación es evitar las ambigüedades o imprecisiones que existen en los lenguajes humanos. Por ejemplo, la representación de valores numéricos en los países anglosajones se realiza separando por comas (,) los millares. Así, trescientos cuarenta y ocho mil quinientos treinta y seis se representa de la siguiente manera:
 
                             348,536
 
Sin embargo, nosotros utilizamos la coma para separar la parte entera de la parte decimal de un número no entero. Por lo tanto, la interpretación con esta regla del número anterior sería: trescientos cuarenta y ocho con quinientas treinta y seis milésimas.
 
A continuación se indican las reglas particulares de Modula-2 para la representación de valores básicos, tanto numéricos como de texto.
 
 
2.3.1 Valores numéricos enteros
Los valores entero representan un número exacto de unidades, y no pueden tener parte fraccionaria. Un valor entero se escribe mediante una secuencia de uno o más dígitos del 0 al  9 sin separadores de ninguna clase entre ellos y precedidos opcionalmente de los símbolos más (+) o menos (-). Son enteros válidos los siguientes:
                       2
                       +56
                       0
                       -234567745
                       1000000000
 
Sin embargo, no son valores enteros válidos los siguientes:
               123,234    No se pueden insertar comas
               22.56       No se pueden insertar puntos
               13E5        No se pueden usar letras
 
Usando la notación BNF podemos representar de manera precisa las reglas para escribir estos valores:
 
              valor_entero ::= [ + | ] secuencia_dígitos
              secuencia_dígitos ::= dígito { dígito }
              dígito ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
 
 
2.3.2 Valores Numéricos Reales
Los valores numéricos reales permiten expresar cualquier cantidad, incluyendo fracciones de unidad. Se pueden representar de dos maneras distintas: en la notación decimal habitual, o en la notación científica. En la notación decimal habitual un valor real se escribe con una parte entera terminada siempre por un punto (.), y seguida opcionalmente por una secuencia de dígitos que constituyen la parte fraccionaria decimal. De acuerdo con ello son valores reales válidos los siguientes:
 
                  5.
                  -0.78
                  +234.53
                  0.0000000034
                  1234.000
 
En la notación científica un número real se escribe como una mantisa, que es un número real en la notación decimal habitual, seguida de un factor de escala que se escribe como la letra E seguida del exponente entero de una potencia de 10 por la que se multiplica la mantisa. Son valores reales válidos en notación científica:
 
                -23.2E+12           equivalente a -23,2 por 10 elevado a 12(10^12)
                14567.823E4        equivalente a 14567,823 x 10^4         
                126.E-34             equivalente a 126×10^-34(diez elevado a menos treinta y cuatro)
 
Sin embargo, no son valores reales válidos los siguientes:
 
                  .234        Se necesita al menos un dígito en la parte entera
                  4,78        No se pueden insertar comas
                  56.7F-56  No se puede usar la letra F
 
A diferencia de los valores enteros, un mismo valor real puede tener muy diversas representaciones válidas. Por ejemplo:
 
     45.6      456.E-1        4.56E+1       45.60E+0         456000.00E-4
 
representan todos el mismo valor.
 
Las reglas anteriores, expresadas en notación BFN son:
 
         valor_real ::= valor_entero . [ secuencia_dígitos ] [ escala ]
         escala ::= E valor_entero
 
 
2.3..3 Caracteres
Además de los valores numéricos enteros o reales, empleados para la realización de cálculos numéricos, los lenguajes de programación nos deben permitir representar valores correspondientes a los caracteres de un texto, y que están disponibles en cualquier teclado, pantalla o impresora.
 
Dentro del texto de un programa en Modula-2 el valor de un carácter concreto se escribe poniendo dicho carácter entre apóstrofos (‘) o comillas ("). Ejemplos de valores de caracteres son los siguientes:
 
            ‘a’   ‘Ñ’   ‘7’   ‘?’   ‘.’   ‘ ‘   ‘"’  ‘}’
 
            "A"  "ñ"   "5"   "!"  ";"  " "  "’"  "{"
 
Es interesante hacer las siguientes observaciones:
 
  • el espacio en blanco (‘ ‘) es un carácter válido como los demás
  • hay que distinguir entre un valor entero de un dígito (p.ej. 7) y el carácter correspondiente a dicho dígito (p.ej. ‘7’)
  • el carácter apóstrofo sólo se puede representar entre comillas, y viceversa
La colección o juego de caracteres que pueden manipularse en un programa depende de la máquina que se esté usando. Sólo se pueden representar en la forma indicada aquellos caracteres que tengan asociado un símbolo gráfico (letra, dígito, signo de puntuación, etc.) que pueda introducirse en el texto del programa. Otros caracteres definidos, tales como los caracteres de control, que no tienen símbolo gráfico se representan mediante la notación CHR (código), tal como se indica en la sección 2.4.4.
 
 
2.3.4 Ristras de caracteres (Strings)
Es frecuente que los caracteres no se utilicen de forma aislada, sino formando palabras o frases. Una ristra o cadena de caracteres (en inglés string) se escribe como una secuencia de caracteres incluidos entres apóstrofos (‘) o comillas ("). Por ejemplo:
 
                ‘Palabra’
                "Este texto es una ristra de caracteres"
                "&"
                ‘El resultado de A+B es: ‘
                "Incluir entre ‘apóstrofos’ el texto"
                ‘Conteste "Si" o "No"’
                "¿ Año de fabricación ?"
                ""
 
Conviene observa que:
  • si una ristra incluye apóstrofos en su interior sólo se podrá escribir entre comillas, y viceversa
  • un valor de tipo carácter se representa igual que una ristra de un único carácter, aunque en realidad son valores de tipos diferentes (el compilador decide cómo interpretarlo)
  • es posible definir una ristra vacía que no contenga ningún carácter, como en el último ejemplo
Una ristra puede contener cualquier número de caracteres y puede incluir cualquier carácter alfabético o de puntuación que sea representable dentro del texto del programa. Aquí se aplican las mismas observaciones que se han hecho antes respecto al juego de caracteres particular de cada máquina.
 
 
2.4 Tipos predefinidos
 
Las diferentes formas de representación de valores constantes presentadas en los apartados anteriores distinguen ya varias clases de datos, pero que no llegan a ser tipos en sí mismos. En efecto, tal como vamos a ver a continuación, dentro de una misma clase de valores pueden distinguirse varios tipos diferentes, tanto a nivel de tipos predefinidos en el lenguaje, como en forma de tipos definidos por el programador.
 
Recordaremos que un tipo de datos define:
  1. una colección de valores posibles
  2. las operaciones significativas sobre ellos
En Modula-2 hay cinco tipos de datos predefinidos, que se designan con los nombres INTEGER, CARDINAL, REAL, BOOLEAN Y CHAR, así como mecanismos para definir nuevos tipos a partir de ellos. En diferentes versiones del lenguaje puede haber tipos predefinidos adicionales. En las secciones siguientes se describen los tipos predefinidos fundamentales, excepto el tipo BOOLEAN, que se describe más adelante.
 
 
2.4.1 El tipo INTEGER
Los valores de este tipo son los valores numéricos enteros positivos y negativos. Como tipo abstracto su definición coincide con el concepto matemático de los números enteros. Sin embargo en cada versión concreta del lenguaje los valores de este tipo se limitan a un cierto rango de valores que pueden manipularse con instrucciones básicas del lenguaje de máquina. El rango depende del computador concreto utilizado, pero siempre es simétrico en torno al valor cero. Dentro de dicho rango la representación de cualquier valor es exacta. Los rangos más comúnmente usados son los siguientes:
 
                               -32.768 … 0 … 32.768
                     -2.147.483.648 … 0 … 2.147.483.648
 
Estos rango obedecen a que los computadores suelen emplear 16 o 32 bits para la codificación en base 2 de los valores enteros. Para el signo del número se utiliza un bit, quedando, por tanto, 15 o31 para el valor absoluto:
 
                              2^15 = 32.768
                              2^31 = 2.147.483.648
 
Para facilitar la escritura de programas que tengan en cuenta la limitación particular de rango existe en cada máquina, Modula-2 permite hacer referencia al valor mínimo mediante la expresión MIN(INTEGER), y al valor máximo mediante MAX(INTEGER). El rango admisible sera, por tanto:
 
                 MIN(INTEGER) … 0 … MAX(INTEGER)
 
Asociadas al tipo INTEGER están las operaciones que se pueden realizar con los valores de este tipo. Las operaciones predefinidas entre valores enteros son las operaciones aritméticas básicas, que se realizan entre enteros y devuelven como resultado valores enteros. Para invocar estas operaciones se dispone de los siguientes símbolos de operación u operadores:
 
                 +         Suma de enteros:                  a+b
                 –         Resta de enteros:                  a-b
                 *         Multiplicación de enteros:        a*b
                 DIV      División de enteros:                a DIV b
                 MOD     Resto de la división:               a MOD b
 
                  +        Identidad de un Entero:                +a
                  –        Cambio de signo de un Entero:        -a
 
Siguiendo la representación aritmética habitual, los símbolos + y – tienen un doble significado, según se usen como operadores infijos entre 2 operandos o como operadores prefijos con un único operando.
 
El operador DIV realiza la división entre dos números enteros y obtiene como resultado el cociente entero truncado al valor más próximo a cero. Cuando el divisor es cero se obtiene como resultado un error. Por ejemplo:
 
              Operación                      Resultado
              10 DIV 3                        3
              (-20) DIV (-7)                2
              (-15) DIV 4                    -3
              17 DIV (-3)                    -5
              34 DIV 0                        Error
 
El operador MOD puede estar sólo definido para divisores positivos. El resultado es el resto de la división de enteros realizada con DIV. Por ejemplo:
 

              Operación                      Resultado
              10 MOD 3                        1
              (-20) MOD (-7)                -6 (o bien Error)
              (-15) MOD 4                    -3
              17 MOD (-3)                    2 (o bien Error)
              34 DIV 0                        Error
 
Entre los operadores DIV y MOD (cuando está definido) existe la regla aritmética habitual:
 
            Dividendo = Divisor x Cociente + Resto
 
que en Modula-2 se expresaría así:
 
            a = (a DIV b) * b + (a MOD b)
 
Cuando se realiza una operación con enteros se debe tener en cuenta el rango disponible en el computador que se esta utilizando. Si se produce un resultado fuera del rango del computador se producirá un error. En algunos computadores este tipo de errores no se indican y puede ser difícil su detección. Por ejemplo, para un rango entre -32.768 y 32.767, se obtienen los siguientes resultados:
 
              Operación                      Resultado
             234 + 89                        323
             345 * 97                        Error
             214 * (-203)                   Error
             15456 + 18678                Error
             (-20) – 32750                  Error
 
 
2.4.2 El tipo CARDINAL
Este tipo representa los valores numéricos enteros no negativos. La definición del tipo CARDINAL no es muy utilizada en la mayoría de los lenguajes. La razón de su incorporación en Modula-2 fue permitir la ampliación del rango de valores positivos en los computadores de 16 bits desde 32.767 has el doble, aprovechando el bit de signo (2^16). Sin embargo, actualmente con los computadores de 32 bits dicho artificio no está ya justificado. Por tanto, cuando el rango de enteros disponible sea amplio es aconsejable no utilizar datos de tipo CARDINAL sino emplear de forma exclusiva datos enteros.
 
En cualquier caso el rango depende del computador concreto que se utilice. La representación de los valores dentro de dicho rango es exacta como en el caso de los valores enteros. Los rangos habituales para los distintos computadores son los siguientes:
 
           0 … 65.535               (16 bits)
           0 … 4.294.967.295     (32 bits)
 
y en forma general el rango será:
 
           0 … MAX(CARDINAL)
 
donde MAX(CARDINAL) representa el valor máximo de los cardinales en el computador concreto utilizado.
 
Con la excepción de la operación de cambio de signo, que no tiene ningún sentido para los cardinales, el resto de las operaciones entre cardinales emplea los mismos operadores que para los números enteros. Esto es debido a que corresponden a las mismas operaciones aritméticas, aunque sobre diferente rango de valores.
 
Aunque los operadores son los mismos, las operaciones entre cardinales sólo pueden realizarse entre cardinales. Por tanto, se produce un error si se trata de ejecutar directamente una operación entre un dato de tipo INTEGER y otro de tipo CARDINAL.
 
 
2.4.3 El tipo REAL
Con este tipo se trata de representar en el computador los valores numéricos reales positivos y negativos. Sin embargo, al contrario que en el caso de los tipos INTEGER y CARDINAL, esta representación puede no ser exacta. Además, dado que la capacidad de los computadores es limitada, la representación sólo se puede considerar válida dentro de un rango.
 
Tanto el rango como la precisión dependen del computador concreto utilizado. Dentro de dicho rango para algunos valores concretos es posible una representación exacta. Sin embargo, dado el carácter discreto de los datos que siempre se manejan en un computador, nunca será posible una representación exacta de valores tales como los valores irracionales (pi) o e o, en general, de valores cuya precisión sea superior a la disponible en el computador que estemos utilizando. En estos casos se manejan valores aproximados.
 
Los valores reales suelen representar internamente en forma equivalente a la notación científica, con una mantisa y un factor de escala. El rango de valores representables está limitado tanto para os valores grandes como pequeños. Los valores más pequeños que un límite dado se confunden con el cero. Algunos de los rangos habitualmente empleados en los distintos computadores son los siguientes:
 
         -3.4E+38 … -1.2E-38   0   -1.2E-38 … +3.4E+38
                            (32 bits, precisión: 6 cifras decimales)
        -1.7E+308 … -2.3E-308   0   +2.3E-308 … +1.7E+308
                            (64 bits, precisión: 15 cifras decimales)
 
Estos rangos dependen del número concreto de bits y de la codificación que se emplean para la mantisa y el exponente del número REAL. En el primer caso no existe ningún valor intermedio entre -1.2×10^-38 y el valor 0, ni tampoco entre 0 y 1.2×10^-38 (análogamente en el segundo).
 
Asociadas al tipo REAL están las operaciones que se pueden realizar con él. Las operaciones entre valores reales son las operaciones aritméticas básicas, que se realizan entre reales y devuelven como resultado valores reales. Los correspondientes operadores son os siguientes:
 
    +          Suma de reales:                        a+b
    –          Resta de reales:                        a-b
    *          Multiplicación de reales:              a*b
    /           División de reales:                     a/b
   
     +          Identidad de un real:                  +a
     –          Cambio de signo de un real:          -a
 
Los símbolos empleados para estos operadores son los mismos que para los operadores enteros, salvo para la división. Sin embargo, en todos los casos son operadores distintos de los operadores enteros. Las operaciones entre reales dan como resultado un real con la precisión del computador. Así, para valores reales no se cumple siempre exactamente la relación básica:
                            (a/b)*b = a
 
y es importante tener en cuenta imprecisiones como ésta cuando los cálculos sean más complejos y se puedan acumular errores. Ejemplos de operaciones entre valores reales son las siguientes:
 
               Operación                                  Resultado
              10.5 / 0.2                                   52.5
              -20.6 * 2.4                                 -49.44
              -15.4E2 + 450.0                           -1090.0
              23.4 – 2E-1                                  23.2
 
La representación sólo aproximada de los valores reales se pone de manifiesto si tratamos de expresar con más precisión de la realmente existente el resultado de una operación. Por ejemplo:
 
              Operación                                  Resultado
              10.0 / 3.0                            3.33333332538604736E+0
 
En este caso concreto el valor es inexacto a partir de la 7ª cifra decimal. En cada máquina se podrá obtener un resultado ligeramente diferente.
 
 
2.4.4 El tipo CHAR
Este tipo incluye como valores todos los caracteres disponibles en un computador. La tabla de caracteres que habitualmente se adopta en la mayoría de los computadores se conoce como tabla ASCII. Esta tabla es fruto de un trabajo de normalización. Sin embargo, hay algunos computadores que no emplean esta tabla y siempre deben tener en cuenta las particularidades del computador en el que se esté trabajando.
 
En cualquier caso la tabla de caracteres, además de los caracteres alfabéticos, incluye caracteres numéricos, de puntuación, y puede incluir caracteres de control. Los caracteres de control, tales como el utilizado para provocar un salto de línea, no se pueden escribir. Para representar estos caracteres se utilizan la notación CHR(x) siendo x el código el carácter (equivalente a su posición dentro de la tabla de todos los caracteres). Por ejemplo, en ASCII:
 
CHR(10)    Representa el salto de línea. Posición 10ª de la tabla
CHR(13)    Representa el retorno de carro. Posición 13ª de la tabla
 
En sentido inverso, la posición que ocupa un determinado carácter c dentro de la tabla se expresa como ORD("c"). Por ejemplo:
 
ORD("A")    Vale 65 (65ª posición de la tabla ASCII)
ORD("Z")    Vale 90 (90ª     "          "          "       )
 
De forma inmediata se puede decir que, para cualquier carácter c, cuya posición sea x, se cumplirá que:
 
CHR(ORD("c")) = "c"
ORD(CHR(x)) = x
 
La mayoría de las tablas de códigos de caracteres poseen las siguientes características:
 
  • Los caracteres correspondientes a las letras mayúsculas de la "A" a la "Z" están ordenados en posiciones consecutivas y crecientes según el orden alfabético.
  • Los caracteres correspondientes a las letras minúsculas de la "a" a la "z" están ordenados en posiciones consecutivas y crecientes según el orden alfabético.
  • Los caracteres correspondientes a los dígitos del "0" al "9" están ordenados en posiciones consecutivas y crecientes.

Esto facilita el obtener por cálculo el valor numérico equivalente al carácter de un dígito decimal, o la letra mayúscula correspondiente a una minúscula o viceversa.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s