8.1.27 Escreva um subprograma de função
(variável independente de ponto fixo) para calcular
. Inclua provisão para rejeição e mensagem de erro adequada se
for negativo.
Nota: Para
inteiro pequeno, multiplicação direta é mais simples. Para
grande, a Equação (8.55), a série de Stirling, seria adequada.
Nota: Para
Passo 1
O enunciado pede um subprograma de função com duas provisões principais: (
) rejeitar valores de
negativos exibindo mensagem de erro, e (
) usar multiplicação direta quando
é pequeno e, para
grande, usar a série de Stirling (Equação
) para aproximar
e em seguida exponenciar.
FACT(N)
para calcular
Passo 2
Validar a entrada: testar se
. Se for verdade, imprimir mensagem de erro e terminar a função retornando valor simbólico (por exemplo
) para indicar falha.
Passo 3
Definir um limite
até o qual se calcula o fatorial exato por multiplicação direta. Por exemplo, escolher
(pois
cabe em precisão dupla). Se
, fazer um laço de
a
multiplicando sucessivamente para obter
.
Passo 4
Para
, usar a aproximação de Stirling. Primeiro calcular
Essa expressão inclui termos de ordem
e
para melhorar a precisão.
Passo 5
Obter a aproximação de
exponenciando o resultado do passo anterior:
Passo 6
Retornar o valor calculado (direto ou aproximado).
Resposta
FUNCTION FACT(N)
! Subprograma para calcular N! (N inteiro >\(=0\))
REAL*\(8\) FACT
INTEGER N, I
REAL*\(8\) F, lnF, x, PI
PARAMETER (PI\(=3.141592653589793\)D\(0\))
INTEGER, PARAMETER :: N\(0=20\)
IF (N .LT. \(0\)) THEN
PRINT *, 'Erro: N deve ser inteiro >\(=0\).'
FACT \(=\) -\(1.0\)D\(0\)
RETURN
END IF
IF (N .LE. N\(0\)) THEN
F \(=1.0\)D\(0\)
DO I \(=2\), N
F \(=\) F * I
END DO
FACT \(=\) F
ELSE
x \(=\) DBLE(N)
lnF \(=\) x*LOG(x) - x \(+0.5\)D\(0\)*LOG(\(2.0\)D\(0\)*PI*x) \(+1.0\)D\(0\)/(\(12.0\)D\(0\)*x) - \(1.0\)D\(0\)/(\(360.0\)D\(0\)*x**\(3\))
FACT \(=\) EXP(lnF)
END IF
END FUNCTION FACT