program torial
implicit none
integer, parameter :: IK = selected_int_kind(18)
integer(IK) :: i
write(*,'(A,$)') 'Number? : '
read(*,*) i
write(*,*) 'Factorial is ',factorial(i)
contains
recursive function factorial( n ) result (f)
integer(IK) :: f, n
if( n == 1 ) then
f = 1
else
f = n * factorial( n - 1_IK )
end if
end function factorial
end program torial
What’s the meaning of the write(*,'(A,$)') used above?
$ rga -A4 "advance='no'.{1,20}end-of-record"
oneapi_fortran_compiler.pdf
For formatted input using nonadvancing I/O (ADVANCE='NO'), an end-of-record (EOR) condition is
returned. If the file was opened with PAD='YES', additional fields are read as spaces.
For list-directed input, another record is read.
For NAMELIST input, another record is read.
For unformatted input, an error occurs.
50! is ~ 3.04E+064
It doesn’t fit into an integer with a range of 18 decimal digits.
Even a 128 bit integer (range = 38) cannot store such a huge number.
A 64 bit real is needed here.
program test_gamma
use iso_fortran_env, only: real64
real(real64) :: x
write(*,'(a)',advance='no') 'Number: '
read(*,*) x
write(*,*) 'Factorial is ', gamma(x+1)
end program test_gamma
For more information, see the following screenshot:
You can’t, because it’s a floating point 64 bits real: you will have at max 16 digits.
If you want to compute big factorials, you will need a Fortran library dealing with arbitrary integer size. Python is adapting the number of bytes needed to code an integer, Fortran is using fixed size integers (generally 8, 16, 32, 64 bits).
Bock in the days before CHARACTER type in Fortran, you could initialize data values with Hollerith values. It was a way of saying “The next n characters should be treated like data”. The 16H references below says use the next 16 characters to fill x(1) and x(2). It was about the only way to create character data in 1966. It was also allowed in FORMAT statements to label output.
double complex x(2)
data x /16Habcdefghijklmnop, 16Hqrstuvwxyz012345/
write( 6, '(4A8, "!")' ) x
end