Trouble with getting Factorial of number

I have written a function to calculate the factorial of x. Here’s the code
implicit none
function factorial(x) result(value)
integer x, value, i
if (x > 0) then
value = 1
do i = 1,x
value = value*i
end do
print *, value
else
print *, “value is invalid”
value = 0
endif
end

integer :: x,y
x = 5
y = factorial(x)
print *, y
end

The error i get is in the image. How do I resolve this issue? Please help

Welcome to the forum. You need to declare the function factorial to be integer in the main program, as in the code below:

function factorial(x) result(value)
integer x, value, i
if (x > 0) then
   value = 1
   do i = 1,x
      value = value*i
   end do
   print *, value
else
   print *, "value is invalid"
   value = 0
end if
end

integer :: x,y,factorial
x = 5
y = factorial(x)
print *, y
end

Also, if you use implicit none in your code, as is recommended, you get a more informative error message from gfortran,

xfactorial.f90:19:13:

   19 | y = factorial(x)
      |             1
Error: Return type mismatch of function 'factorial' at (1) (UNKNOWN/INTEGER(4))
xfactorial.f90:19:4:

   19 | y = factorial(x)
      |    1
Error: Function 'factorial' at (1) has no IMPLICIT type

It is also recommended to put functions and subroutines in modules. The code would be

module factorial_mod
implicit none
contains
function factorial(x) result(value)
integer x, value, i
if (x > 0) then
   value = 1
   do i = 1,x
      value = value*i
   end do
   print *, value
else
   print *, "value is invalid"
   value = 0
end if
end function factorial
end module factorial_mod

program main
use factorial_mod
implicit none
integer :: x,y
x = 5
y = factorial(x)
print *, y
end program main

It is legal to use single-letter variables such as x or y as integer if they are declared as such, but I would use a letter from i to n to avoid surprising the reader.

2 Likes

For future reference, Fortran has a gamma() function, which for positive whole numbers can be used to calculate factorials.

Factorials grow so rapidly that you will overflow a 32-bit INTEGER quite quickly.

Even typical DOUBLEPRECISION will overflow past 170! and Fortran is basically not required to indicate when overflow occurs (although compilers can commonly report it, depending on the compiler options used).

Of course factorials are often shown calculated via recursion, as it can be done with very little code, so you will often find recursive versions.

open calculate factorial in Fortran Playground

!  GAMMA(X) computes Gamma of X. For positive whole number values of N the
!  Gamma function can be used to calculate factorials, as (N-1)! ==
!  GAMMA(REAL(N)). That is
!
!      n! == gamma(real(n+1))
!
program demo_gamma
use, intrinsic :: iso_fortran_env, only: wp => real64, int64
implicit none
integer :: i, j

   ! gamma() is related to the factorial function
   do i = 1, 171
      ! check value is not too big for default integer type
      if (factorial(i)  <=  huge(0)) then
         write (*, *) i, nint(factorial(i)), 'integer'
      elseif (factorial(i)  <=  huge(0_int64)) then
         write (*, *) i, nint(factorial(i),kind=int64), 'integer(kind=int64)'
      else
         write (*, *) i, factorial(i) , 'user factorial function'
         write (*, *) i, product([(real(j, kind=wp), j=1, i)]), 'product'
         write (*, *) i, gamma(real(i + 1, kind=wp)), 'gamma directly'
      end if
   end do


contains
   function factorial(i) result(f)
      integer, intent(in) :: i
      real(kind=wp) :: f
      if (i  <=  0) then
         write (*, '(*(g0))') '<ERROR> gamma(3) function value ', i, ' <= 0'
         stop '<STOP> bad value in gamma function'
      end if
      f = gamma(real(i + 1,kind=wp))
   end function factorial
end program demo_gamma
2 Likes

There is also an intrinsic log_gamma() function for arguments that are too large to represent gamma() as a floating point value.

2 Likes