Справка по алгоритму Fortran - получение неверных результатов - PullRequest
1 голос
/ 19 марта 2012

Я сейчас работаю над матричным калькулятором на фортране.У меня есть программа компиляции, и она работает, за исключением того, что я не получаю правильные результаты.Когда я выбираю функцию сложения, моя программа принимает две матрицы и складывает их вместе.Мой результат, кажется, выходит из строя.Например, если я выберу две матрицы размером 2х2 и списком 1, в качестве каждой записи я получу результат сложения 3,3,3.Я не могу понять, где я ошибся в алгоритме.Я еще не проверял другие алгоритмы, так как пытаюсь исправить один алгоритм за раз.Ниже мой код

  *START PROGRAM
  PROGRAM MAIN

  *DECLARATIONS
  INTEGER SELECTION, DONE, VALID, J, I, K, M, N
  INTEGER, DIMENSION(10,10):: SUM, A, B

  *INTITIALIZE
  M = 0
  N = 0
  J = 0
  I = 0
  K = 0
  DONE = 1
  VALID = 1

  *LOOP UNTIL USER CHOOSES TO QUIT

  DO WHILE(DONE .GT. 0)

  *DISPLAY MENU UNTIL VALID ENTRY IS ENTERED

  DO WHILE (VALID .GT. 0)
  *PRINT MENU
  PRINT *,'MATRIX CALCULATOR'
  PRINT *,'PLEASE MAKE A SELECTION'
  PRINT *,'1) MATRIX ADDITION'
  PRINT *,'2) MATRIX SUBTRACTION'
  PRINT *,'3) MATRIX MULTIPLICATION'
  PRINT *,'4) MATRIX TRANSPOSE'
  PRINT *,'5) QUIT PROGRAM'
  READ (*,*) SELECTION

  *VALID ENTRY CHECK
  IF (SELECTION .GT. 5 .OR. SELECTION .LT. 1) THEN
  PRINT *,'PLEASE ENTER A VALID SELECTION'
  ELSE 
  VALID= -1
  END IF

  *END WHEN VALID ENTRY IS ENTERED
  END DO

  *QUIT?
  IF (SELECTION .EQ. 5) THEN
  DONE = -1
  ELSE
  *OTHERWISE CONTINUE
  *GET DIMENTIONS INPUT 
  PRINT *,'PLEASE ENTER THE DIMENTIONS'
  PRINT *,'ENTER IN M:'
  READ (*,*) M
  PRINT *,'ENTER IN N:'
  READ (*,*) N
  *GET IN MATRIX
  PRINT *, 'PLEASE ENTER IN MATRIX A'
  DO J=1, M
  DO I=1, N
  PRINT *, 'ENTER IN VALUE I, I', J, I
  READ(*,*) A(M,N)
  END DO
  END DO

  PRINT *, 'PLEASE ENTER IN MATRIX B'
  DO J=1, M
  DO I=1, N
  PRINT *, 'ENTER IN VALUE I, I', J,I
  READ(*,*) B(M,N)
  END DO
  END DO

  *PERFORM DESIRED CALCULATION
  SELECT CASE(SELECTION)
  *CASE 1
  CASE (1)
   PRINT *,'MATRIX ADDITION'
   DO J=1,M
   DO I=1,N
   SUM(J,I)=A(J,I)+B(J,I)
   END DO   
   END DO

  *PRINT ADDITION RESULT
   PRINT *,'ADDITION RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) SUM(J,I)
   END DO
   END DO
  *CASE 2
  CASE (2)
   PRINT *,'MATRIX SUBTRACTION'
   DO J=1,M
   DO I=1,N
   SUM(J,I)=A(J,I)-B(J,I)
   END DO   
   END DO

  *PRINT SUBTRACTION RESULT
   PRINT *,'SUBTRACTION RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) SUM(J,I)
   END DO
   END DO
  *CASE 3
  CASE (3)
   PRINT *,'MATRIX MULTIPLICATION'
   DO J=1, M
   DO I=1, N
   DO K=1, N
   SUM(J,I) = SUM(J,I)+A(J,K)*B(I,J)
   END DO
   END DO
   END DO

  *PRINT MULTIPLICATION RESULT
   DO J=1, M
   DO I=1, N
   WRITE (*,*) SUM(J,I)
   END DO
   END DO
  *CASE 4
  CASE (4)
   PRINT *,'MATRIX TRANSPOSE'
   DO J=1, M
   DO I=1, N
   B(I,J) = A(J,I)
   END DO
   END DO
  *PRINT TRANSPOSE RESULT
   PRINT *, 'MATRIX A RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) A(J,I)
   END DO
   END DO
   PRINT *, 'MATRIX B RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) B(J,I)
   END DO
   END DO
  CASE DEFAULT
   PRINT *,'SOMETHING HAS GONE WRONG'
  END SELECT

  *USER SELECTED TO QUIT
  END IF
  END DO
  PRINT *, 'PROGRAM HAS ENDED'
  *END PROGRAM
  STOP
  END

Ответы [ 5 ]

4 голосов
/ 19 марта 2012

Один из способов избежать ошибок, которые вы допустили, - использовать функции массива Fortran. Например, вы можете суммировать массивы A и B, если они имеют одинаковый размер, с помощью одного оператора:

C = A + B

Вы также можете использовать встроенные процедуры matmul и transpose для умножения и транспонирования матрицы соответственно.

3 голосов
/ 19 марта 2012

Основная проблема заключается в том, что при чтении матриц вы читаете их по неправильным индексам.вместо READ(*,*) A(M,N) и READ(*,*) B(M,N) у вас должны быть READ(*,*) A(J,I) и READ(*,*) B(J,I)

. В дополнение к этому вам нужно иметь выделяемые массивы вместо объявления суммы, A и B в качестве измерения (1,1).Я также считаю, что именование массива SUM - это плохая практика, поскольку оно совпадает с именем встроенной функции Фортрана, поэтому я назвал ее здесь C.Объявите их так:

integer, allocatable, dimension(:,:) :: A, B, C

, затем, прочитав измерения от пользователя, сделайте следующее:

allocate(A(m, n))

С этими изменениями я получаю (2,2; 2,2) при добавлении (1,1; 1,1) к (1,1; 1,1).

В общем, я бы также предложил правильно сделать отступ в ваших циклах и не использовать все заглавные буквы, он делает коднамного труднее читать.

1 голос
/ 19 марта 2012

Некоторые ошибки, отмеченные в других ответах (например, внешняя подписка), могут автоматически распознаваться компиляторами, если вы выбираете соответствующие тесты времени выполнения. Выбор расширенных параметров предупреждения и проверки ошибок компилятора поможет вам быстрее находить ошибки. Какой компилятор вы используете?

1 голос
/ 19 марта 2012

Вы объявляете SUM, A и B массивами 1x1, а затем в программе вы ссылаетесь на них вне их объявленных границ. Все может случиться.

1 голос
/ 19 марта 2012

Это проблема:

  *PRINT ADDITION RESULT
   PRINT *,'ADDITION RESULT'
   DO J=1, M
   DO I=1, N
   WRITE (*,*) SUM(N,M)
   END DO
   END DO

Вы должны иметь WRITE (*,*) SUM(J,I).

...