|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
arctica
Joined: 10 Sep 2006 Posts: 118 Location: United Kingdom
|
Posted: Sat Jan 04, 2025 5:52 pm Post subject: Factorial |
|
|
Hello
The factorial function crops up quite a lot would it be handy as an intrinsic function in ftn95? Just a thought.
Code: | program factorial_test
implicit none
! Store integers as 64-bit to handle very large numbers
integer(kind=4) :: n
integer(kind=4) :: fact_result
! Test the function with n = 20
n = 20
fact_result = factorial(n)
! Output the result
print *, "Factorial of ", n, " is: ", fact_result
contains
recursive function factorial(n) result(fact)
integer(kind=4) :: n
integer(kind=4) :: fact
! Check for negative or zero values
if (n < 0) then
print *, "Error: Factorial is not defined for negative numbers."
fact = -1 ! Error code for negative input
else if (n == 0) then
fact = 1 ! Factorial of 0 is 1
else
fact = n * factorial(n - 1) ! Recursive case
end if
end function factorial
end program factorial_test
|
A quick code testing a large value.
Lester |
|
Back to top |
|
|
Kenneth_Smith
Joined: 18 May 2012 Posts: 753 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Sat Jan 04, 2025 9:47 pm Post subject: |
|
|
Lester,
Using the 64 bit compiler, you could do this calculation in one line of fortran.
Use an implied do loop within an array constructor, and then apply the product intrinsic to the array.
Code: | program fact
implicit none
integer :: n
integer(4) :: ifact
integer(4) :: i
real*8 :: dfact
do n = -1, 20, 1
ifact = max( 0, product( [(i, i=1, n, 1)] ) ) ! Max required with /Checkmate
write(*,'(I3,A,I20)') n, '! = ' , ifact
end do
write(*,*)
do n = 20, 170, 10
dfact = max ( 0.d0, product( [(dble(i), i=1, n, 1)] ) )
write(*,'(I3,A,EN20.8)') n, '! = ' , dfact
end do
end program fact |
|
|
Back to top |
|
|
Kenneth_Smith
Joined: 18 May 2012 Posts: 753 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Sat Jan 04, 2025 11:22 pm Post subject: |
|
|
The code I posted earlier is not portable to other compilers, because of a programmer error!
Code below is, which explicitly deals with negative and zero values of n.
For n .ge. 1 the implied do loop / array constructor / product intrinsic remains the same, which is the real point I was trying to demonstrate.
Code: | program fact
implicit none
integer(4) :: n
integer(4) :: ifact
integer :: i
real*8 :: dfact
do n = -1, 20, 1
ifact = ifactorial(n)
write(*,'(I3,A,I20)') n, '! = ' , ifact
end do
write(*,*)
do n = 20, 170, 10
dfact = dfactorial(n)
write(*,'(I3,A,EN20.8)') n, '! = ' , dfact
end do
contains
function ifactorial(n) result(sol)
integer(4), intent(in) :: n
integer(4) :: i
integer(4) :: sol
sol = 0
if (n .ge. 1) sol = product( [(i, i=1, n, 1)] )
if (n .eq. 0) sol = 1
end function ifactorial
function dfactorial(n) result(sol)
integer(4), intent(in) :: n
integer :: i
real*8 :: sol
sol = 0.d0
if (n .ge. 1) sol = product( [(dble(i), i=1, n, 1)] )
if (n .eq. 0) sol = 1.d0
end function dfactorial
end program fact |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8087 Location: Salford, UK
|
Posted: Sun Jan 05, 2025 7:51 am Post subject: |
|
|
Lester
Is there a function like this in the Fortran Standard?
Our focus with respect to development has to be on conforming to the lastest standards. |
|
Back to top |
|
|
arctica
Joined: 10 Sep 2006 Posts: 118 Location: United Kingdom
|
Posted: Sun Jan 05, 2025 1:34 pm Post subject: |
|
|
Thanks for the ideas Ken, code works fine.
I am not aware of factorial being an intrinsic in the latest standard.
One thing we do have in ftn95 is the Gamma function. I know this only works on reals, so not sure how it can be flipped to give the same integer output as Ken's code?
In simple terms, Factorial(n) = Gamma(n + 1). In ftn95 the following works up to n=12, but fails for any value that is greater.
Code: | program test_gamma_factorial
implicit none
real(kind=2) :: n = 12.0d0
real(kind=2):: fact
fact = gamma(n+1.0d0)
print *, "Factorial of ", int(n), " is ", int(fact)
end program test_gamma_factorial |
Lester |
|
Back to top |
|
|
Kenneth_Smith
Joined: 18 May 2012 Posts: 753 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Sun Jan 05, 2025 3:08 pm Post subject: |
|
|
Lester, These answer both of your questions.
Code: | program q1
implicit none
integer :: n
real*8 :: fact
integer :: i
do i = 1, 25
n = i
fact = gamma( min( n, 20 ) + 1.0d0 )
print *, "Factorial of ", int(n), " is ", int(fact,kind=4)
end do
end program q1 |
Code: | program q2
implicit none
real*8 :: fact
integer :: i
do i = 1, 175, 1
fact = gamma( min( i, 170 ) + 1.0d0)
print *, "Factorial of ", i, " is ", fact
end do
end program q2 |
|
|
Back to top |
|
|
arctica
Joined: 10 Sep 2006 Posts: 118 Location: United Kingdom
|
Posted: Wed Jan 08, 2025 5:58 pm Post subject: |
|
|
Thanks for the update Ken.
In conclusion, we can say it is not required as an intrinsic function. A good discussion and helpful coding ideas.
Lester |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|