8.1.27 Escreva um subprograma de função F A C T(N) (variável independente de ponto fixo) para calcular N!. Inclua provisão para rejeição e mensagem de erro adequada se N for negativo.
Nota: Para N inteiro pequeno, multiplicação direta é mais simples. Para N grande, a Equação (8.55), a série de Stirling, seria adequada.

Passo 1

O enunciado pede um subprograma de função FACT(N) para calcular N! com duas provisões principais: ( 1) rejeitar valores de N negativos exibindo mensagem de erro, e ( 2) usar multiplicação direta quando N é pequeno e, para N grande, usar a série de Stirling (Equação 8.55) para aproximar \ln(N!) e em seguida exponenciar.

Passo 2

Validar a entrada: testar se N<0. Se for verdade, imprimir mensagem de erro e terminar a função retornando valor simbólico (por exemplo -1) para indicar falha.

Passo 3

Definir um limite N_0 até o qual se calcula o fatorial exato por multiplicação direta. Por exemplo, escolher N_0=20 (pois 20! cabe em precisão dupla). Se 0\le N\le N_0, fazer um laço de 1 a N multiplicando sucessivamente para obter N!.

Passo 4

Para N>N_0, usar a aproximação de Stirling. Primeiro calcular
\ln(N!) \approx N\ln N - N + \tfrac12\ln(2\pi N) + \frac{1}{12N} - \frac{1}{360N^3}
Essa expressão inclui termos de ordem O(N^{-1}) e O(N^{-3}) para melhorar a precisão.

Passo 5

Obter a aproximação de N! exponenciando o resultado do passo anterior:
N! \approx \exp\bigl(\ln(N!)\bigr).

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

Exercícios de Livros Relacionados