How can I print a formatted array of factorials from 1-100 without errors?

  • Thread starter Thread starter Sue Parks
  • Start date Start date
  • Tags Tags
    Array
AI Thread Summary
The discussion revolves around a Fortran program designed to calculate and store factorials from 1 to 100 in an array. The user initially encounters an error when attempting to print the array due to using a real number as an index, which is not permitted. Suggestions include converting the real index to an integer and cleaning up the code by removing unused variables. The program is revised to correctly allocate an array for factorials and print them, but issues arise with variable types, particularly the mismatch between the precision of the variable used for calculations and the array type. The solution involves ensuring both the factorial variable and the array are declared with the same precision, preferably double precision, to handle larger values without overflow. The discussion highlights the importance of proper variable types and array indexing in Fortran programming.
Sue Parks
Messages
38
Reaction score
0
I have a list of factorials from 1 -100. I can print them to the console without a format problem. I used the kind() function for formatting the output. I have tried to put these numbers into an array, but I get an error when I try to print the array
PRINT *, FACTORIALS (F)
1
Warning: Legacy Extension: REAL array index at (1)

Fortran:
PROGRAM CALCULATE_FACTORIAL
IMPLICIT NONE
INTEGER, PARAMETER:: DIGITS = SELECTED_REAL_KIND(2,40)
REAL (KIND=DIGITS) :: F
REAL, allocatable, DIMENSION(:) :: FACTORIALS ! array that will hold the primes
INTEGER:: A, N
REAL :: ELEMENTS, I

ALLOCATE (FACTORIALS(n))

FACTORIALS (1)= 1.0

F = 1.0
N = 1
I =1
ELEMENTS =0
A=0 

DO 
print *, F
N =N +1
F =F * N
!F = ELEMENTS
IF ( N == 101 ) THEN
EXIT
END IF
PRINT *, FACTORIALS (F)
END DODEALLOCATE (FACTORIALS)END PROGRAM CALCULATE_FACTORIAL
 
Technology news on Phys.org
Sue Parks said:
I have a list of factorials from 1 -100. I can print them to the console without a format problem. I used the kind() function for formatting the output. I have tried to put these numbers into an array, but I get an error when I try to print the array
PRINT *, FACTORIALS (F)
1
Warning: Legacy Extension: REAL array index at (1)

Fortran:
PROGRAM CALCULATE_FACTORIAL
IMPLICIT NONE
INTEGER, PARAMETER:: DIGITS = SELECTED_REAL_KIND(2,40)
REAL (KIND=DIGITS) :: F
REAL, allocatable, DIMENSION(:) :: FACTORIALS ! array that will hold the primes
INTEGER:: A, N
REAL :: ELEMENTS, I

ALLOCATE (FACTORIALS(n))

FACTORIALS (1)= 1.0

F = 1.0
N = 1
I =1
ELEMENTS =0
A=0

DO
print *, F
N =N +1
F =F * N
!F = ELEMENTS
IF ( N == 101 ) THEN
EXIT
END IF
PRINT *, FACTORIALS (F)
END DODEALLOCATE (FACTORIALS)END PROGRAM CALCULATE_FACTORIAL
The problem that is causing the error you see is the print statement near the bottom of your code. The index of an array has to be in integer value. The expression FACTORIALS(F) has an array index that is real.

Some other comments:
  1. DIGITS is not being used, so should be deleted.
  2. ELEMENTS is set to 0, and not used after that. It too should be deleted.
  3. A is set to 0 but not used after that. It should be deleted.
  4. Your DO loop could be changed to a DO I = 1, 101 loop.
  5. The variable F and the assignment statement F = F * N should be removed. Instead of having a separate variable F, just assign values to the appropriate spot in the FACTORIALS array.
  6. I don't think you need two separate variables I and N.
Having extra, unused variables in a program is not a good thing, as it makes it more difficult for a reader to understand what's going on.
 
I HAVE CLEANED UP THE PROGRAM. I AM TRYING TO USE THE KIND() FUNCTION TO GET THE VALUES. I HAVE THE EXPONENTIAL VALUES, BUT I AM CURIOUS ABOUT FILLING THESE VALUES INTO AN ARRAY (SEE COMMENTS). THANKS

SAMPLE OUTPUT:
Sues-MacBook-Air:FORTRAN sueparks$ gfortran CALCULATE_FACTORIAL.f90
Sues-MacBook-Air:FORTRAN sueparks$ ./a.out
1 1.00000000000000000000000000000000000
2 2.00000000000000000000000000000000000
3 6.00000000000000000000000000000000000
4 24.0000000000000000000000000000000000
5 120.000000000000000000000000000000000
6 720.000000000000000000000000000000000
7 5040.00000000000000000000000000000000
8 40320.0000000000000000000000000000000
9 362880.000000000000000000000000000000
10 3628800.00000000000000000000000000000
11 39916800.0000000000000000000000000000
12 479001600.000000000000000000000000000
13 6227020800.00000000000000000000000000
14 87178291200.0000000000000000000000000
15 1307674368000.00000000000000000000000
16 20922789888000.0000000000000000000000

Fortran:
PROGRAM CALCULATE_FACTORIAL
        IMPLICIT NONE
        INTEGER, PARAMETER:: M = 100
        REAL (KIND = 16) ::  FACT
        !INTEGER  ::  F = SELECTED_INT_KIND(2,40)
      
      
        !INTEGER, DIMENSION (M) :: FACTORIAL  ! ADD FACTORIALS TO ARRAY
      
        INTEGER :: I
        
          FACT = 1
          DO i = 1, M
              FACT = FACT * I
              PRINT *,I , FACT
              !WRITE (*,*) FACTORIAL (FACT)
          END DO

  
    END PROGRAM CALCULATE_FACTORIAL
 
Last edited by a moderator:
Sue Parks said:
I HAVE CLEANED UP THE PROGRAM. I AM TRYING TO USE THE KIND() FUNCTION TO GET THE VALUES. I HAVE THE EXPONENTIAL VALUES, BUT I AM CURIOUS ABOUT FILLING THESE VALUES INTO AN ARRAY (SEE COMMENTS). THANKS

SAMPLE OUTPUT:
Sues-MacBook-Air:FORTRAN sueparks$ gfortran CALCULATE_FACTORIAL.f90
Sues-MacBook-Air:FORTRAN sueparks$ ./a.out
1 1.00000000000000000000000000000000000
2 2.00000000000000000000000000000000000
3 6.00000000000000000000000000000000000
4 24.0000000000000000000000000000000000
5 120.000000000000000000000000000000000
6 720.000000000000000000000000000000000
7 5040.00000000000000000000000000000000
8 40320.0000000000000000000000000000000
9 362880.000000000000000000000000000000
10 3628800.00000000000000000000000000000
11 39916800.0000000000000000000000000000
12 479001600.000000000000000000000000000
13 6227020800.00000000000000000000000000
14 87178291200.0000000000000000000000000
15 1307674368000.00000000000000000000000
16 20922789888000.0000000000000000000000

Fortran:
PROGRAM CALCULATE_FACTORIAL
        IMPLICIT NONE
        INTEGER, PARAMETER:: M = 100
        REAL (KIND = 16) ::  FACT
        !INTEGER  ::  F = SELECTED_INT_KIND(2,40)
     
     
        !INTEGER, DIMENSION (M) :: FACTORIAL  ! ADD FACTORIALS TO ARRAY
     
        INTEGER :: I
       
          FACT = 1
          DO i = 1, M
              FACT = FACT * I
              PRINT *,I , FACT
              !WRITE (*,*) FACTORIAL (FACT)
          END DO

 
    END PROGRAM CALCULATE_FACTORIAL
What's your question?
 
  • Like
Likes Sue Parks
How to fill an array
 
Sue Parks said:
How to fill an array

Fortran:
program test
  integer, parameter ::  M = 100
  integer, dimension(M):: Arr
  integer i

  do i = 1, M
      Arr(i) = 2 * i + 3  ! Or whatever
  enddo
end program test

After this program runs, the array Arr will have the values 3, 5, 7, 9, ... , 203 in its 100 cells.

I don't have a fortran compiler any more, so I don't 100% guarantee the above code. It's pretty simple, so it should run as advertised.
 
  • Like
Likes Sue Parks
I have tried this. It is obvious that I get and array! BUT the output is not correct.
Sues-MacBook-Air:FORTRAN sueparks$ gfortran CALCULATE_FACTORIAL.f90
Sues-MacBook-Air:FORTRAN sueparks$ ./a.out

0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
Fortran:
Real, DIMENSION (M) :: FACTORIAL  ! ADD FACTORIALS TO ARRAY
  
  
    
          Fact = 1
          DO i = 1, M
              FACTORIAL = FACT * I
        
              PRINT *, factorial
        
          END DO
 
Last edited by a moderator:
Sue Parks said:
I have tried this. It is obvious that I get and array! BUT the output is not correct.
Sues-MacBook-Air:FORTRAN sueparks$ gfortran CALCULATE_FACTORIAL.f90
Sues-MacBook-Air:FORTRAN sueparks$ ./a.out

0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
Fortran:
Real, DIMENSION (M) :: FACTORIAL  ! ADD FACTORIALS TO ARRAY
 
 
   
          Fact = 1
          DO i = 1, M
              FACTORIAL = FACT * I
       
              PRINT *, factorial
       
          END DO
factorial (AKA FACTORIAL in your code) is an array. To access it, include an index, as in factorial(i).

The code should look more like this:
Fortran:
     Fact = 1
     DO i = 1, M
          Fact = Fact * i
          Factorial(i) = Fact
     END DO

     ! Now you can display the factorials
     DO I = 1, M
          Print *, Factorial(I)
     END DO
Using the unformatted print statement won't give you the nice output that a formatted WRITE statement will, but we can save that for another time. If you're curious, do a web search for "fortran write".

BTW, I applaud your attempts to use code tags, but they should look like this
Fortran:
 -- no spaces inside the brackets
-- use forward slash and no spaces
 
  • Like
Likes Sue Parks
  • #10
I used the kind () function to help. I AM using the WRITE command to write to a file. When I used the PRINT command, I was able to print to 100.
33 8.68331788E+36
34 2.95232803E+38
35 Infinity
36 Infinity
37 Infinity

Fortran:
        IMPLICIT NONE
        INTEGER, PARAMETER:: M = 100
        REAL (KIND = 16) ::  FACT
        Real, DIMENSION (M) :: FACTORIAL  ! ADD FACTORIALS TO ARRAY
        INTEGER  :: I
      
          OPEN (11,  FILE = "MY_FACTORIALS.out", ACTION = "WRITE")
          Fact = 1
          DO i = 1, M
              FACT = FACT * I
              FACTORIAL(I) = FACT
          END DO  
        
          DO I = 1, M
              !PRINT *, FACTORIAL (I)
              WRITE (11,*) I, FACTORIAL (I)  !  PRINT ARRAY
          END DO
          CLOSE(11)
 
  • #11
Sue Parks said:
I used the kind () function to help. I AM using the WRITE command to write to a file. When I used the PRINT command, I was able to print to 100.
33 8.68331788E+36
34 2.95232803E+38
35 Infinity
36 Infinity
37 Infinity

Fortran:
        IMPLICIT NONE
        INTEGER, PARAMETER:: M = 100
        REAL (KIND = 16) ::  FACT
        Real, DIMENSION (M) :: FACTORIAL  ! ADD FACTORIALS TO ARRAY
        INTEGER  :: I
     
          OPEN (11,  FILE = "MY_FACTORIALS.out", ACTION = "WRITE")
          Fact = 1
          DO i = 1, M
              FACT = FACT * I
              FACTORIAL(I) = FACT
          END DO 
       
          DO I = 1, M
              !PRINT *, FACTORIAL (I)
              WRITE (11,*) I, FACTORIAL (I)  !  PRINT ARRAY
          END DO
          CLOSE(11)
The fact that this code blew up at 35 has nothing to do with differences between print and write. The reason your values are overflowing for 35 and larger is that you have a mismatch between the variable Fact and your array Factorial. The Fact variable is declared as REAL (KIND=16), while the Factorial array is declared merely as REAL.

Since you're using gfortran, KIND=16 is probably allocating 8 bytes for Fact, not 16 bytes as the KIND value might suggest. See http://people.sc.fsu.edu/~jburkardt/f_src/real_precision/real_precision.html, right under "Examples and Tests". Each element of your array is probably a single-precision real of four bytes, which can hold a maximum value of about ##10^{38}##. 8-byte reals can hold much larger values, but when you try to stuff an 8-byte quantity into a space in the array that can hold only 4 bytes, it won't fit.

More info on the gfortran KIND type parameters: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gfortran/KIND-Type-Parameters.html#KIND-Type-Parameters. Depending on the particular compiler you have, REALs are probably limited to 4 or 8 bytes, and your KIND=16 is likely not helping much. If it were my program, I would make Fact and Factorial DOUBLE PRECISION, which would make them both 8-byte reals.

BTW, your thread title is misleading: "Print a Formatted Array". There is no such thing as a "formatted array." You can print an array using formatted printing, which is where WRITE with a FORMAT statement comes in.
 
  • Like
Likes Sue Parks
  • #12
I did change FACT and FACTORIAL to DOUBLE PRECISION and that did help. Thank YOU!
 

Similar threads

Replies
4
Views
2K
Replies
13
Views
3K
Replies
23
Views
2K
Replies
5
Views
3K
Replies
3
Views
2K
Replies
8
Views
3K
Replies
2
Views
8K
Back
Top