viernes, 8 de junio de 2012

Aritmética en el Lenguaje de Programación C

Antes de hablar de aritmética en el lenguaje C, vamos a hablar simplemente de la aritmética.
¿Cuál es el resultado de la siguiente operación?

5 + 4 x 6 = ?

Muchas personas responden de inmediato que el resultado es 54, porque si se suma 5 + 4 el resultado es 9; si ahora se multiplica 9 x 6, el resultado es 54. Otras contestan que el resultado es 29, porque 4 x 6 = 24, y 5 + 24 = 29.
Este ejemplo es ilustrativo, porque muestra claramente que en aritmética es importante el orden en el cual los operadores actúan. Esta importancia es más grande todavía en programación. La respuesta correcta es la segunda,

5 + 4 x 6 = 29

La razón de ésto es que por convención, la multiplicación tiene un orden de precedencia mayor que la suma. Las operaciones NO se realizan en el orden de aparición de los operadores. La norma es, primero se realizan las multiplicaciones y divisiones y luego sumas y restas. Cuando en una expresión aritmética sólo aparecen sumas (restas) o sólo multiplicaciones (divisiones), el orden en el que se realicen estas operaciones sí es indiferente. El lector tal vez recuerda estos resultados como las leyes asociativas y conmutativas de la suma(resta) y la multiplicación (división): el orden de los sumandos no altera la suma y el orden de los factores no altera el producto.
Los operadores aritméticos binarios del lenguaje c son

_______________________________________________________________
|OPERADORES ARITMETICOS BINARIOS DEL LENGUAJE DE PROGRAMACION C|
_______________________________________________________________
|SIMBOLO EN C   | EQUIVALENTE MATEMATICO | EJEMPLO             |
________________________________________________________________
|      *        |            x           |  5*7 = 35           |
________________________________________________________________
|      /        |            /           |  15/3 = 5           |
_______________________________________________________________
|      +        |            +           |  7 + 4 = 11         |
________________________________________________________________
|      -        |            -           |  14 - 8 = 6         |
________________________________________________________________
|      %        |            %           |  9%2 = 1            |
_______________________________________________________________


Los operadores aritméticos de suma, resta y división son los mismos en C y en matemáticas. No así el operador de multiplicación, que en C es *. La razón de ésto, es que el lenguaje toma cualquier letra, como x ó X, como nombres de variables y no como operadores. El signo * está reservado para ser el operador de multiplicación. El lector está familiarizado con dichas operaciones, y no será necesario abundar en ellas. Probablemente el operador de módulo % no sea tan familiar. Éste operador recibe dos enteros y devuelve el residuo de la que queda al realizar la división de tales números. En el ejemplo presentado en la tabla de arriba, el cociente (entero) de 9/2 = 4, y el residuo es 1.
Para alterar el orden natural de ejecución de los operadores es necesario usar paréntesis. Si en el caso de la suma presentada al principio, usamos un par de paréntesis como éstos, que rodean al 5 y al 4

(5 + 4) x 6 = 54

obtendremos como resultado 54. Los paréntesis indican que lo contenido dentro de ellos, debe considerarse como un sólo número. Primero deben hacerse pues, las operaciones indicadas ahí, y el resultado final multiplicarlo por 6. Casos más complicados pueden aparecer cuando hay más de un par de paréntesis y algunos de ellos están anidados

((4 - 6) - 7*(2 + (-8)) = ?

4 pares de paréntesis aparecen aquí. El primero, externo, rodea a toda la expresión. Ese podría ser suprimido sin ningún problema. Sin embargo, muchas veces, cuando escriba programas, verá que es útil rodear una expresión aritmética con paréntesis externos. El siguiente par rodea a 4 - 6. Esto quiere decir, como en el caso anterior, que hay que considerar esa expresión como un sólo número; ese número es -2. El siguiente par de paréntesis rodea a 2 + (-8). El otro par de paréntesis rodea a -8. En realidad también es redundante, ya que podría haberse escrito 2 - 8, pero la literal también es válida. El resultado de esa expresión es -6. Así que, suprimiendo los paréntesis internos, la expresión queda como

-2 - 7*(-6) = ?

Aquí sólo aparece un par de paréntesis, rodeando a -6. Primero se realiza la multiplicación, -7*(-6) = 42. -2 + 42 = 40. El resultado es 40.
Para la potenciación, logaritmo y raíz cuadrada, el lenguaje C incluye funciones preestablecidas. Éstas funciones están empacadas en el encabezado <stdio.h>

Sin embargo, hay que tener en cuenta que en C los números reales son almacenados en espacios de memoria, y el resultado de las operaciones aritméticas que con ellos se realizan, también. Las operaciones entre números enteros (int) producen un int; las operaciones entre float produce números float. Sin embargo, no es posible realizar, por ejemplo, la suma de un tipo int con un tipo float. En caso de ocurrir una operación de ese tipo, el compilador convierte el tipo int a tipo float de manera implícita, y el resultado es un float. En general la regla es que los tipos menores se convierten a los tipos mayores, lo cual ocurre sin pérdida de precisión. En general, y a pesar de dicha conversión, no es conveniente permitir que ocurran tales casos. El almacenamiento de un tipo float (producto de una operación aritmética) en un tipo int no es posible, y el intento produce un mensaje de error.
Los operadores en una expresión aritmética podrían ser funciones de variables. Por ejemplo:

int a, s, t;

a = f(s) + g(t)

En este fragmento de programa, a la variable entera a se le asigna la suma de los valores de retorno (tipos int) de las funciones f (que depende del parámetro entero s) y g (dependiente, a su vez, del parámetro entero t). En casos como éste, el estándar de C no indica qué función se evalúa primero. Un compilador, en una computadora podría evaluar primero g(t) y luego f(s), en tanto que otro compilador (o incluso el mismo) en una computadora distinta, puede hacer la evaluación al revés. Esto es especialmente grave si las funciones dependen del mismo parámetro y lo modifican en los cuerpos de instrucciones.
También es necesario cuidar la precedencia cuando uno escribe segmentos de código como

a[i] = i++;

Los operadores de incremento y decremento pueden producir sutiles errores cuando se usa la variable incrementada o decrementada en la misma expresión. En este ejemplo, el estándar no dice qué se hace primero, si incrementar el contador o localizar el espacio de memoria en el arreglo. Como recomendación contra éstos errores, es necesario evitar expresiones en las que el resultado depende el orden de evaluación de los elementos de dichas expresiones.
Vale aquí una digresión que no está del todo fuera de lugar. El procesador de una computadora para fines teóricos es llamado unidad de proceso (PU por sus siglas en inglés). Una PU consta de dos partes: la unidad lógica aritmética (ALU) y la unidad de control (CU). La primera es capaz de realizar sumas, restas, etc. y llevar a cabo operaciones lógicas del tipo igual que, mayor o igual que, etc; en tanto que la segunda coordina la realización de esas tareas aritméticas y lógicas. La ALU sólo puede llevar a cabo una operación a la vez, por lo cual es importante el papel jugado por la CU al asignarle las tareas mediante las instrucciones adecuadas. Estas instrucciones se realizan con un orden determinado y en conjunto se les conoce como ciclo de instrucción. Éstos pasos son:
Buscar y traer (Fetch) La PU busca y trae la siguiente instrucción del programa que está ejecutando.
Decodificar la instrucción LA PU tiene que saber qué tipo de instrucción va a realizar la ALU (suma, multiplicación, división, etc.)
Ejecutar la instrucción Esta es la tarea realizada por la ALU.
Almacenar el resultado El resultado de la operación aritmética o lógica realizada por la ALU es almacenada en memoria para su posterior utilización.
Todas las computadoras realizan este ciclo de instrucción, y todo lo que saben hacer las computadoras es solamente esto. Es sorprendente que audio, video,comunicación remota y todas las tareas para las que sirven las computadoras sean realizadas llevando a cabo sólo operaciones lógicas y aritméticas, pero así es. Tan importante es este ciclo, que los procesadores valen por la cantidad de ciclos de instrucción que pueden hacer en un segundo. Un procesador de 3 GHz realiza 3 x 1000000000 ciclos por segundo.
Ninguna tarea tiene control absoluto del procesador. Todas las tareas se enlistan y se efectúan con un orden que depende de la prioridad que tiene la tarea. Los sistemas operativos se crearon para administrar las tareas que hará el procesador y el tiempo asignado a ellas.

No hay comentarios:

Publicar un comentario en la entrada

Related Posts Plugin for WordPress, Blogger...