InicioEjemplos

Producto escalar entre dos vectores

Un ejemplo sencillo para motivar el desarrollo del enlace entre la expresión matemática y el código.

Vamos a plantear el problema paso a paso primero de forma matemática y pasarlo a código FORTRAN.

Antes de nada tenemos que empezar nuestro programa como siempre con una línea con el nombre del programa. Este nombre puede ser lo que sea y tampoco va a influir en el resto del programa. Elija el que más le guste. Recuerda que todas las líneas deben empezar en la séptima columna excepto los comentarios, las líneas continuadas y los formatos. Para poner un comentario, es decir una línea de código que solo sirve de información al programador y se ignora a la hora de compilar, se pone una C en la segunda columna. Todo el texto que siga será el comentario.

      PROGRAM PRODESCA

 C    DECLARACIONES

Ahora sabemos que vamos a tener que hacer el producto escalar entre dos vectores. Para ello vamos a necesitar dos vectores de la misma dimensión. Es decir, tienen el mismo número de elementos e índices.

Suponemos aquí que estamos usando la declaración implícita de variables por defecto donde las variables serán de un tipo u otro dependiendo de la primera letra de su nombre. Las letras A a H y O a Z corresponden a REAL e I a N corresponden a enteros. Aún así tenemos que declarar explícitamente la dimensión. Para este ejemplo elegimos la dimensión igual a seis. Vamos a llamar a nuestros vectores V1 y V2. La dimensión de una variable implícitamente definida se define escribiendo DIMENSION seguido por el nombre de la variable y su dimensión en paréntesis.

      PROGRAM PRODESCA

 C    DECLARACIONES
      
      DIMENSION V1(6),V2(6)

Cabe comentar que la dimensión tiene que fijarse explícitamente en el código antes de compilar y por tanto para ajustar la dimensión del vector hay que cambiar el código y volver a compilar el programa. Volveremos sobre esto más adelante para ver como se puede cambiar la dimensión a la hora de ejecutar sin tener que volver a compilar.

Ahora lo que queremos es pedir al usuario que introduzca los componentes de los dos vectores. Para cada vector tenemos que tomar el mismo número de entradas como dimensiones tenga el vector. Podríamos especificar cada componente explícitamente pero no es una solución muy elegante y tampoco se presta muy bien al cambio de la dimensión del vector. Entonces, usamos un bucle DO para iterar el componente del vector sobre el cuál tomamos la entrada.

      PROGRAM PRODESCA

 C    DECLARACIONES
      
      DIMENSION V1(6),V2(6)

 C    ENTRADA
      
      WRITE(*,*) 'Datos de V1'

      DO I=1,6
      	READ(*,*) V1(I)
      END DO

Esto mismo podemos conseguirlo de forma todavía más compacta. Se pueden introducir bucles DO implícitos en la misma línea que la lectura de la siguiente forma. Completamos el ejemplo para incluir la entrada del segundo vector.

      PROGRAM PRODESCA

 C    DECLARACIONES
      
      DIMENSION V1(6),V2(6)

 C    ENTRADA
      
      WRITE(*,*) 'Datos de V1'
      READ(*,*) (V1(I), I=1,6)
      WRITE(*,*) 'Datos de V2'
      READ(*,*) (V2(I), I=1,6)

Los WRITE y READ tienen dos argumentos. La primera estrellita quiere decir que se tome la salida o lectura por el dispositivo por defecto: la pantalla. La segunda entrada define el formato de la lectura o salida. Una estrellita indica que queremos usar el formato por defecto. Al final del programa insistiremos más en los formatos.

Ahora estamos preparados para calcular el producto escalar de los vectores introducidos. El producto escalar entre dos vectores está definido como

donde es la dimensión de los vectores y los y son los componentes i-ésimos de cada vector.

Es obvio de la definición que lo que tenemos que hacer es ir acumulando términos de una suma. Cuando aparece una suma se puede traducir en un bucle DO de forma directa. Como vamos a ir acumulando valores en una variable tenemos que poner ésta a cero primero.

Ojo: como es un REAL hay que especificar el punto decimal. Hay algunos compiladores donde esto no es estríctamente necesario pero es una buena práctica de todas maneras.

      PROGRAM PRODESCA

 C    DECLARACIONES
      
      DIMENSION V1(6),V2(6)

 C    ENTRADA
      
      WRITE(*,*) 'Datos de V1'
      READ(*,*) (V1(I), I=1,6)
      WRITE(*,*) 'Datos de V2'
      READ(*,*) (V2(I), I=1,6)

 C    CALCULO

      ESCA=0.0

      DO I=1,6
      	ESCA = ESCA + V1(I)*V2(I)
      END DO

Este bucle quiere decir que para cada valor de se iguala la variable de acumulación a su valor en la iteración anterior más el producto de los componentes i-ésimos de cada vector. Es claro que este algoritmo iterativo es totalmente equivalente a la definición matemática del producto escalar.

Ahora solo queda tomar la salida del resultado a la pantalla. Para que quede un poco más bonito queremos escribir a la pantalla una frase que indica lo que es el dato que viene a continuación. Para escribir varias cosas con el mismo WRITE se escriben cada una separada por una coma.

      PROGRAM PRODESCA

 C    DECLARACIONES
      
      DIMENSION V1(6),V2(6)

 C    ENTRADA
      
      WRITE(*,*) 'Datos de V1'
      READ(*,*) (V1(I), I=1,6)
      WRITE(*,*) 'Datos de V2'
      READ(*,*) (V2(I), I=1,6)

 C    CALCULO

      ESCA=0.0

      DO I=1,6
      	ESCA = ESCA + V1(I)*V2(I)
      END DO

 C    SALIDA

      WRITE(*,100) 'El producto escalar de V1 y V2 vale',ESCA

 C    FORMATOS
  100 FORMAT (A35,1X,F7.2)

      END

Vamos a usar este momento para explicar los formatos. Los formatos se etiquetan con números que empiezan en la cuarta columna. Especificando este número en el comando WRITE se le aplica el formato correspondiente. Hay que especificar el tipo de salida para cada miembro del WRITE. Entre paréntesis ponemos primero el formato de la frase. Cuando la salida es de caractéres se pone una A seguido por el número de caractéres. Para meter espacios se utiliza una X con el número de espacios deseados delante. Por último especificamos con F que ESCA va a ser un REAL y que queremos siete cifras como mucho con dos cifras decimales.

¡Que no se te olvide terminar el programa con un END!

Dimensión dinámica

Hemos visto como hacer el producto escalar de dos vectores de cierta dimensión. El problema que tiene nuestro programa es que la dimensión del vector tiene que ir fijado explícitamente en el programa de tal manera que necesitamos un programa nuevo para vectores de dimensión distinta. Vamos a ver ahora como podemos evitar este problema y tomar la dimensión como otra entrada más al programa.

Sería oportuno poder definir la dimensión directamente como otra variable más que se tome como entrada

      PROGRAM PRODESCA

 C    DECLARACIONES

      WRITE(*,*) 'Introduzca la dimensión de los vectores'
      READ(*,*) N
      
      DIMENSION V1(N),V2(N)

Esto es incorrecto y no se puede compilar. Todas las declaraciones tienen que ir antes que cualquier otra cosa como puede ser READ o WRITE. Lo único que podemos hacer es fijar una dimensión máxima del vector y declarar los vectores de esa dimensión. Para nuestro ejemplo queremos una dimensión máxima de diez

      PROGRAM PRODESCA

 C    DECLARACIONES

      NMAX=10      
      DIMENSION V1(NMAX),V2(NMAX)

y luego tomar la dimensión que queremos usar como otra entrada más.

      PROGRAM PRODESCA

 C    DECLARACIONES

      NMAX=10      
      DIMENSION V1(NMAX),V2(NMAX)

      WRITE(*,*) 'Introduzca la dimensión de los vectores'
      READ(*,*) N

y adaptamos el resto del programa modificando el límite superior de los bucles para ser la dimensión especificada.

      PROGRAM PRODESCA

 C    DECLARACIONES

      NMAX=10      
      DIMENSION V1(NMAX),V2(NMAX)

 C    ENTRADA

      WRITE(*,*) 'Introduzca la dimensión de los vectores'
      READ(*,*) N
      
      WRITE(*,*) 'Datos de V1'
      READ(*,*) (V1(I), I=1,N)
      WRITE(*,*) 'Datos de V2'
      READ(*,*) (V2(I), I=1,N)

 C    CALCULO

      ESCA=0.0

      DO I=1,N
      	ESCA = ESCA + V1(I)*V2(I)
      END DO

 C    SALIDA

      WRITE(*,100) 'El producto escalar de V1 y V2 vale',ESCA

 C    FORMATOS
  100 FORMAT (A35,1X,F7.2)

      END

Ojo: este método tiene una pega. Hay que tener cuidado a la hora de poner la dimensión máxima porque aunque no usemos todas las dimensiones el programa sí utiliza toda la memoría que ocupa un vector de la dimensión máxima. Si ponemos dimensiones razonables no será un problema pero utilizar muchos vectores definidos de esta manera con dimensión máxima elevada puede usar una cantidad de memoria excesiva.