Fortran - Guia Rápido

Fortran, derivado do Formula Translating System, é uma linguagem de programação imperativa de uso geral. É usado para computação numérica e científica.

O Fortran foi originalmente desenvolvido pela IBM na década de 1950 para aplicações científicas e de engenharia. Fortran governou essa área de programação por muito tempo e se tornou muito popular para computação de alto desempenho, porque.

Suporta -

  • Análise numérica e computação científica
  • Programação estruturada
  • Programação de matriz
  • Programação modular
  • Programação genérica
  • Computação de alto desempenho em supercomputadores
  • Programação orientada a objetos
  • Programação simultânea
  • Grau razoável de portabilidade entre sistemas de computador

Fatos sobre Fortran

  • O Fortran foi criado por uma equipe liderada por John Backus na IBM em 1957.

  • Inicialmente, o nome costumava ser escrito em maiúsculas, mas os padrões e implementações atuais exigem apenas que a primeira letra seja maiúscula.

  • Fortran significa FORmula TRANslator.

  • Originalmente desenvolvido para cálculos científicos, tinha suporte muito limitado para cadeias de caracteres e outras estruturas necessárias para programação de propósito geral.

  • Extensões e desenvolvimentos posteriores o tornaram uma linguagem de programação de alto nível com bom grau de portabilidade.

  • As versões originais Fortran I, II e III são consideradas obsoletas agora.

  • A versão mais antiga ainda em uso é o Fortran IV e o Fortran 66.

  • As versões mais comumente usadas hoje são: Fortran 77, Fortran 90 e Fortran 95.

  • O Fortran 77 adicionou strings como um tipo distinto.

  • Fortran 90 adicionou vários tipos de threading e processamento direto de array.

Configurando Fortran no Windows

G95 é o compilador multi-arquitetônico GNU Fortran, usado para configurar o Fortran no Windows. A versão do Windows emula um ambiente Unix usando MingW no Windows. O instalador cuida disso e adiciona automaticamente g95 à variável PATH do Windows.

Você pode obter a versão estável do G95 aqui

Como usar o G95

Durante a instalação, g95é adicionado automaticamente à sua variável PATH se você selecionar a opção “RECOMENDADO”. Isso significa que você pode simplesmente abrir uma nova janela do Prompt de Comando e digitar “g95” para abrir o compilador. Encontre alguns comandos básicos abaixo para começar.

Sr. Não Comando e Descrição
1

g95 –c hello.f90

Compila hello.f90 para um arquivo de objeto denominado hello.o

2

g95 hello.f90

Compila hello.f90 e o vincula para produzir um executável a.out

3

g95 -c h1.f90 h2.f90 h3.f90

Compila vários arquivos de origem. Se tudo correr bem, os arquivos de objeto h1.o, h2.o e h3.o são criados

4

g95 -o hello h1.f90 h2.f90 h3.f90

Compila vários arquivos de origem e os vincula a um arquivo executável chamado 'hello'

Opções de linha de comando para G95

-c Compile only, do not run the linker.
-o Specify the name of the output file, either an object file or the executable.

Vários arquivos de origem e de objeto podem ser especificados de uma vez. Os arquivos Fortran são indicados por nomes que terminam em ".f", ".F", ".for", ".FOR", ".f90", ".F90", ".f95", ".F95", ". f03 "e" .F03 ". Vários arquivos de origem podem ser especificados. Os arquivos de objeto também podem ser especificados e serão vinculados para formar um arquivo executável.

Um programa Fortran é feito de uma coleção de unidades de programa, como um programa principal, módulos e subprogramas ou procedimentos externos.

Cada programa contém um programa principal e pode ou não conter outras unidades de programa. A sintaxe do programa principal é a seguinte -

program program_name
implicit none      

! type declaration statements      
! executable statements  

end program program_name

Um programa simples em Fortran

Vamos escrever um programa que adiciona dois números e imprime o resultado -

program addNumbers

! This simple program adds two numbers
   implicit none

! Type declarations
   real :: a, b, result

! Executable statements
   a = 12.0
   b = 15.0
   result = a + b
   print *, 'The total is ', result

end program addNumbers

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

The total is 27.0000000

Observe que -

  • Todos os programas Fortran começam com a palavra-chave program e terminar com a palavra-chave end program, seguido do nome do programa.

  • o implicit nonedeclaração permite que o compilador verifique se todos os seus tipos de variáveis ​​estão declarados corretamente. Você deve sempre usarimplicit none no início de cada programa.

  • Os comentários no Fortran são iniciados com o ponto de exclamação (!), Pois todos os caracteres após isso (exceto em uma sequência de caracteres) são ignorados pelo compilador.

  • o print * comando exibe dados na tela.

  • O recuo das linhas de código é uma boa prática para manter um programa legível.

  • Fortran permite letras maiúsculas e minúsculas. Fortran não faz distinção entre maiúsculas e minúsculas, exceto para literais de string.

Fundamentos

o basic character set de Fortran contém -

  • as letras A ... Z e a ... z
  • os dígitos 0 ... 9
  • o caractere sublinhado (_)
  • os caracteres especiais =: + espaço em branco - * / () [],. $ '! "% &; <>?

Tokenssão feitos de caracteres no conjunto de caracteres básico. Um token pode ser uma palavra-chave, um identificador, uma constante, um literal de string ou um símbolo.

As declarações do programa são feitas de tokens.

Identificador

Um identificador é um nome usado para identificar uma variável, procedimento ou qualquer outro item definido pelo usuário. Um nome em Fortran deve seguir as seguintes regras -

  • Não pode ter mais de 31 caracteres.

  • Deve ser composto de caracteres alfanuméricos (todas as letras do alfabeto e os dígitos de 0 a 9) e sublinhados (_).

  • O primeiro caractere de um nome deve ser uma letra.

  • Os nomes não diferenciam maiúsculas de minúsculas

Palavras-chave

Palavras-chave são palavras especiais, reservadas para o idioma. Essas palavras reservadas não podem ser usadas como identificadores ou nomes.

A tabela a seguir lista as palavras-chave Fortran -

As palavras-chave não I / O
alocável distribuir atribuir tarefa bloquear dados
ligar caso personagem comum complexo
contém continuar ciclo dados desalocar
padrão Faz dupla precisão outro mais se
em outro lugar dados do bloco final fim fazer função final fim se
interface final módulo final fim do programa fim selecionar fim da sub-rotina
tipo final terminar onde entrada equivalência Saída
externo função vamos para E se implícito
dentro entrada inteiro intenção interface
intrínseco tipo len lógico módulo
lista de nomes anular operador opcional
Fora parâmetro pausa ponteiro privado
programa público real recursivo resultado
Retorna Salve  Selecionar caso Pare sub-rotina
alvo então tipo tipo() usar
Onde Enquanto
As palavras-chave relacionadas ao I / O
backspace Fechar endfile formato investigar
abrir impressão ler rebobinar Escreva

Fortran fornece cinco tipos de dados intrínsecos, no entanto, você também pode derivar seus próprios tipos de dados. Os cinco tipos intrínsecos são -

  • Tipo inteiro
  • Tipo real
  • Tipo complexo
  • Tipo lógico
  • Tipo de personagem

Tipo Inteiro

Os tipos inteiros podem conter apenas valores inteiros. O exemplo a seguir extrai o maior valor que pode ser mantido em um número inteiro normal de quatro bytes -

program testingInt
implicit none

   integer :: largeval
   print *, huge(largeval)
   
end program testingInt

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

2147483647

Observe que o huge()função fornece o maior número que pode ser mantido pelo tipo de dados inteiro específico. Você também pode especificar o número de bytes usando okindespecificador. O exemplo a seguir demonstra isso -

program testingInt
implicit none

   !two byte integer
   integer(kind = 2) :: shortval
   
   !four byte integer
   integer(kind = 4) :: longval
   
   !eight byte integer
   integer(kind = 8) :: verylongval
   
   !sixteen byte integer
   integer(kind = 16) :: veryverylongval
   
   !default integer 
   integer :: defval
        
   print *, huge(shortval)
   print *, huge(longval)
   print *, huge(verylongval)
   print *, huge(veryverylongval)
   print *, huge(defval)
   
end program testingInt

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

32767
2147483647
9223372036854775807
170141183460469231731687303715884105727
2147483647

Tipo Real

Ele armazena os números de ponto flutuante, como 2.0, 3.1415, -100.876, etc.

Tradicionalmente, existem dois tipos reais diferentes, o padrão real digite e double precision tipo.

No entanto, o Fortran 90/95 fornece mais controle sobre a precisão dos tipos de dados reais e inteiros por meio do kind especificador, que estudaremos no capítulo sobre Números.

O exemplo a seguir mostra o uso de tipo de dados real -

program division   
implicit none  

   ! Define real variables   
   real :: p, q, realRes 
   
   ! Define integer variables  
   integer :: i, j, intRes  
   
   ! Assigning  values   
   p = 2.0 
   q = 3.0    
   i = 2 
   j = 3  
   
   ! floating point division
   realRes = p/q  
   intRes = i/j
   
   print *, realRes
   print *, intRes
   
end program division

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

0.666666687    
0

Tipo Complexo

Isso é usado para armazenar números complexos. Um número complexo possui duas partes, a parte real e a parte imaginária. Duas unidades de armazenamento numérico consecutivas armazenam essas duas partes.

Por exemplo, o número complexo (3,0, -5,0) é igual a 3,0 - 5,0i

Discutiremos os tipos complexos com mais detalhes, no capítulo Números.

Tipo Lógico

Existem apenas dois valores lógicos: .true. e .false.

Tipo de personagem

O tipo de caractere armazena caracteres e strings. O comprimento da string pode ser especificado pelo especificador len. Se nenhum comprimento for especificado, é 1.

For example,

character (len = 40) :: name  
name = “Zara Ali”

A expressão, name(1:4) daria a substring “Zara”.

Digitação Implícita

Versões mais antigas do Fortran permitiam um recurso chamado digitação implícita, ou seja, você não precisa declarar as variáveis ​​antes de usar. Se uma variável não for declarada, a primeira letra de seu nome determinará seu tipo.

Nomes de variáveis ​​que começam com i, j, k, l, m ou n são considerados variáveis ​​inteiras e outros são variáveis ​​reais. No entanto, você deve declarar todas as variáveis, pois é uma boa prática de programação. Para isso, você inicia seu programa com a declaração -

implicit none

Esta instrução desativa a digitação implícita.

Uma variável nada mais é que um nome dado a uma área de armazenamento que nossos programas podem manipular. Cada variável deve ter um tipo específico, que determina o tamanho e o layout da memória da variável; a faixa de valores que podem ser armazenados nessa memória; e o conjunto de operações que podem ser aplicadas à variável.

O nome de uma variável pode ser composto de letras, dígitos e o caractere de sublinhado. Um nome em Fortran deve seguir as seguintes regras -

  • Não pode ter mais de 31 caracteres.

  • Deve ser composto de caracteres alfanuméricos (todas as letras do alfabeto e os dígitos de 0 a 9) e sublinhados (_).

  • O primeiro caractere de um nome deve ser uma letra.

  • Os nomes não diferenciam maiúsculas de minúsculas.

Com base nos tipos básicos explicados no capítulo anterior, a seguir estão os tipos de variáveis ​​-

Sr. Não Tipo e descrição
1

Integer

Ele pode conter apenas valores inteiros.

2

Real

Ele armazena os números de ponto flutuante.

3

Complex

É usado para armazenar números complexos.

4

Logical

Ele armazena valores booleanos lógicos.

5

Character

Ele armazena caracteres ou strings.

Declaração de Variável

As variáveis ​​são declaradas no início de um programa (ou subprograma) em uma instrução de declaração de tipo.

A sintaxe para declaração de variável é a seguinte -

type-specifier :: variable_name

Por exemplo

integer :: total  	
real :: average 
complex :: cx  
logical :: done 
character(len = 80) :: message ! a string of 80 characters

Mais tarde, você pode atribuir valores a essas variáveis, como,

total = 20000  
average = 1666.67   
done = .true.   
message = “A big Hello from Tutorials Point” 
cx = (3.0, 5.0) ! cx = 3.0 + 5.0i

Você também pode usar a função intrínseca cmplx, atribuir valores a uma variável complexa -

cx = cmplx (1.0/2.0, -7.0) ! cx = 0.5 – 7.0i 
cx = cmplx (x, y) ! cx = x + yi

Exemplo

O exemplo a seguir demonstra a declaração, atribuição e exibição de variáveis ​​na tela -

program variableTesting
implicit none

   ! declaring variables
   integer :: total      
   real :: average 
   complex :: cx  
   logical :: done 
   character(len=80) :: message ! a string of 80 characters
   
   !assigning values
   total = 20000  
   average = 1666.67   
   done = .true.   
   message = "A big Hello from Tutorials Point" 
   cx = (3.0, 5.0) ! cx = 3.0 + 5.0i

   Print *, total
   Print *, average
   Print *, cx
   Print *, done
   Print *, message
   
end program variableTesting

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

20000
1666.67004    
(3.00000000, 5.00000000 )
T
A big Hello from Tutorials Point

As constantes referem-se aos valores fixos que o programa não pode alterar durante sua execução. Esses valores fixos também são chamadosliterals.

As constantes podem ser de qualquer tipo de dados básicos, como uma constante inteira, uma constante flutuante, uma constante de caractere, uma constante complexa ou um literal de string. Existem apenas duas constantes lógicas:.true. e .false.

As constantes são tratadas como variáveis ​​regulares, exceto que seus valores não podem ser modificados após sua definição.

Constantes e literais nomeados

Existem dois tipos de constantes -

  • Constantes literais
  • Constantes nomeadas

Uma constante literal tem um valor, mas nenhum nome.

Por exemplo, a seguir estão as constantes literais -

Tipo Exemplo
Constantes inteiras 0 1 -1 300 123456789
Constantes reais 0,0 1,0 -1,0 123,456 7,1E + 10 -52,715E-30
Constantes complexas (0,0, 0,0) (-123,456E + 30, 987,654E-29)
Constantes lógicas .verdadeiro. .falso.
Constantes de personagem

"PQR" "a" "123'abc $% # @!"

" uma citação "" "

'PQR' 'a' '123 "abc $% # @!'

'um apóstrofo' ''

Uma constante nomeada tem um valor e também um nome.

As constantes nomeadas devem ser declaradas no início de um programa ou procedimento, assim como uma declaração de tipo de variável, indicando seu nome e tipo. As constantes nomeadas são declaradas com o atributo de parâmetro. Por exemplo,

real, parameter :: pi = 3.1415927

Exemplo

O programa a seguir calcula o deslocamento devido ao movimento vertical sob a gravidade.

program gravitationalDisp

! this program calculates vertical motion under gravity 
implicit none  

   ! gravitational acceleration
   real, parameter :: g = 9.81   
   
   ! variable declaration
   real :: s ! displacement   
   real :: t ! time  
   real :: u ! initial speed  
   
   ! assigning values 
   t = 5.0   
   u = 50  
   
   ! displacement   
   s = u * t - g * (t**2) / 2  
   
   ! output 
   print *, "Time = ", t
   print *, 'Displacement = ',s  
   
end program gravitationalDisp

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

Time = 5.00000000    
Displacement = 127.374992

Um operador é um símbolo que informa ao compilador para executar manipulações matemáticas ou lógicas específicas. Fortran fornece os seguintes tipos de operadores -

  • Operadores aritméticos
  • Operadores Relacionais
  • Operadores lógicos

Vejamos todos esses tipos de operadores, um por um.

Operadores aritméticos

A tabela a seguir mostra todos os operadores aritméticos suportados pelo Fortran. Assumir variávelA detém 5 e variável B segura 3 então -

Mostrar exemplos

Operador Descrição Exemplo
+ Operador de adição, adiciona dois operandos. A + B dará 8
- Operador de subtração, subtrai o segundo operando do primeiro. A - B dará 2
* Operador de multiplicação, multiplica ambos os operandos. A * B dará 15
/ Operador de divisão, divide o numerador pelo de-numerador. A / B dará 1
** Operador de exponenciação, eleva um operando à potência do outro. A ** B dará 125

Operadores Relacionais

A tabela a seguir mostra todos os operadores relacionais suportados pelo Fortran. Assumir variávelA contém 10 e variável B contém 20, então -

Mostrar exemplos

Operador Equivalente Descrição Exemplo
== .eq. Verifica se os valores dos dois operandos são iguais ou não, se sim a condição torna-se verdadeira. (A == B) não é verdade.
/ = .ne. Verifica se os valores de dois operandos são iguais ou não, se os valores não são iguais, a condição se torna verdadeira. (A! = B) é verdade.
> .gt. Verifica se o valor do operando esquerdo é maior que o valor do operando direito, se sim então a condição torna-se verdadeira. (A> B) não é verdade.
< .lt. Verifica se o valor do operando esquerdo é menor que o valor do operando direito; se sim, a condição torna-se verdadeira. (A <B) é verdade.
> = .ge. Verifica se o valor do operando esquerdo é maior ou igual ao valor do operando direito, se sim a condição torna-se verdadeira. (A> = B) não é verdade.
<= .le. Verifica se o valor do operando esquerdo é menor ou igual ao valor do operando direito; em caso afirmativo, a condição torna-se verdadeira. (A <= B) é verdadeiro.

Operadores lógicos

Operadores lógicos em Fortran funcionam apenas em valores lógicos .true. e .false.

A tabela a seguir mostra todos os operadores lógicos suportados pelo Fortran. Assuma que a variável A contém .true. e a variável B contém .false. , então -

Mostrar exemplos

Operador Descrição Exemplo
.e. Operador lógico chamado AND. Se ambos os operandos forem diferentes de zero, a condição se torna verdadeira. (A .e. B) é falso.
.ou. Operador lógico ou chamado. Se qualquer um dos dois operandos for diferente de zero, a condição se torna verdadeira. (A .ou. B) é verdade.
.não. Operador lógico chamado NOT. Use para reverter o estado lógico de seu operando. Se uma condição for verdadeira, o operador NOT lógico tornará falso. ! (A .e. B) é verdade.
.eqv. Operador lógico denominado EQUIVALENT. Usado para verificar a equivalência de dois valores lógicos. (A .eqv. B) é falso.
.neqv. Operador Lógico NÃO EQUIVALENTE Chamado. Usado para verificar a não equivalência de dois valores lógicos. (A .neqv. B) é verdade.

Precedência de operadores em Fortran

A precedência do operador determina o agrupamento de termos em uma expressão. Isso afeta como uma expressão é avaliada. Certos operadores têm precedência mais alta do que outros; por exemplo, o operador de multiplicação tem precedência mais alta do que o operador de adição.

Por exemplo, x = 7 + 3 * 2; aqui, x é atribuído a 13, não 20, porque o operador * tem precedência mais alta do que +, portanto, primeiro é multiplicado por 3 * 2 e, em seguida, é adicionado a 7.

Aqui, os operadores com a precedência mais alta aparecem na parte superior da tabela, aqueles com a mais baixa aparecem na parte inferior. Em uma expressão, os operadores de precedência superior serão avaliados primeiro.

Mostrar exemplos

Categoria Operador Associatividade
NOT lógico e sinal negativo .não. (-) Da esquerda para direita
Exponenciação ** Da esquerda para direita
Multiplicativo * / Da esquerda para direita
Aditivo + - Da esquerda para direita
Relacional <<=>> = Da esquerda para direita
Igualdade == / = Da esquerda para direita
E lógico .e. Da esquerda para direita
OR lógico .ou. Da esquerda para direita
Tarefa = Direita para esquerda

As estruturas de tomada de decisão requerem que o programador especifique uma ou mais condições a serem avaliadas ou testadas pelo programa, junto com uma instrução ou instruções a serem executadas, se a condição for determinada como verdadeira, e, opcionalmente, outras instruções a serem executadas se o condição é determinada como falsa.

A seguir está a forma geral de uma estrutura típica de tomada de decisão encontrada na maioria das linguagens de programação -

Fortran fornece os seguintes tipos de construções de tomada de decisão.

Sr. Não Declaração e descrição
1 Se ... então construa

if… then… end if declaração consiste em uma expressão lógica seguida por uma ou mais declarações.

2 Se ... então ... outra construção

if… then declaração pode ser seguida por um opcional else statement, que é executado quando a expressão lógica é falsa.

3 if ... else if ... else Declaração

A if construção de instrução pode ter um ou mais opcionais else-ifconstrói. Quando oif condição falha, o imediatamente seguido else-ifÉ executado. Quando oelse-if também falha, seu sucessor else-if instrução (se houver) for executada e assim por diante.

4 aninhado se construir

Você pode usar um if ou else if declaração dentro de outra if ou else if afirmações).

5 selecionar construção de caso

UMA select case instrução permite que uma variável seja testada quanto à igualdade em relação a uma lista de valores.

6 construção de caso de seleção aninhada

Você pode usar um select case declaração dentro de outra select case afirmações).

Pode haver uma situação em que você precise executar um bloco de código várias vezes. Em geral, as instruções são executadas sequencialmente: a primeira instrução em uma função é executada primeiro, seguida pela segunda e assim por diante.

As linguagens de programação fornecem várias estruturas de controle que permitem caminhos de execução mais complicados.

Uma instrução de loop nos permite executar uma instrução ou grupo de instruções várias vezes e a seguir está a forma geral de uma instrução de loop na maioria das linguagens de programação -

Fortran fornece os seguintes tipos de construções de loop para lidar com os requisitos de loop. Clique nos links a seguir para verificar seus detalhes.

Sr. Não Tipo de Loop e Descrição
1 fazer loop

Essa construção permite que uma declaração, ou uma série de declarações, seja executada iterativamente, enquanto uma determinada condição for verdadeira.

2 fazer loop while

Repete uma declaração ou grupo de declarações enquanto uma determinada condição for verdadeira. Ele testa a condição antes de executar o corpo do loop.

3 loops aninhados

Você pode usar uma ou mais construções de loop dentro de qualquer outra construção de loop.

Declarações de controle de loop

As instruções de controle de loop alteram a execução de sua sequência normal. Quando a execução deixa um escopo, todos os objetos automáticos que foram criados nesse escopo são destruídos.

Fortran suporta as seguintes instruções de controle. Clique nos links a seguir para verificar seus detalhes.

Sr. Não Declaração de controle e descrição
1 Saída

Se a instrução exit for executada, o loop será encerrado e a execução do programa continuará na primeira instrução executável após a instrução end do.

2 ciclo

Se uma instrução de ciclo for executada, o programa continua no início da próxima iteração.

3 Pare

Se você deseja que a execução do seu programa pare, você pode inserir uma instrução de parada

Os números em Fortran são representados por três tipos de dados intrínsecos -

  • Tipo inteiro
  • Tipo real
  • Tipo complexo

Tipo Inteiro

Os tipos inteiros podem conter apenas valores inteiros. O exemplo a seguir extrai o maior valor que poderia ser mantido em um número inteiro normal de quatro bytes -

program testingInt
implicit none

   integer :: largeval
   print *, huge(largeval)
   
end program testingInt

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

2147483647

Observe que o huge()função fornece o maior número que pode ser mantido pelo tipo de dados inteiro específico. Você também pode especificar o número de bytes usando okindespecificador. O exemplo a seguir demonstra isso -

program testingInt
implicit none

   !two byte integer
   integer(kind = 2) :: shortval
   
   !four byte integer
   integer(kind = 4) :: longval
   
   !eight byte integer
   integer(kind = 8) :: verylongval
   
   !sixteen byte integer
   integer(kind = 16) :: veryverylongval
   
   !default integer 
   integer :: defval
        
   print *, huge(shortval)
   print *, huge(longval)
   print *, huge(verylongval)
   print *, huge(veryverylongval)
   print *, huge(defval)
   
end program testingInt

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

32767
2147483647
9223372036854775807
170141183460469231731687303715884105727
2147483647

Tipo Real

Ele armazena os números de ponto flutuante, como 2.0, 3.1415, -100.876, etc.

Tradicionalmente, havia dois diferentes real tipos: o tipo real padrão e double precision tipo.

No entanto, o Fortran 90/95 fornece mais controle sobre a precisão dos tipos de dados reais e inteiros por meio do kind especificador, que estudaremos em breve.

O exemplo a seguir mostra o uso de tipo de dados real -

program division   
implicit none

   ! Define real variables   
   real :: p, q, realRes 
   
   ! Define integer variables  
   integer :: i, j, intRes  
   
   ! Assigning  values   
   p = 2.0 
   q = 3.0    
   i = 2 
   j = 3  
   
   ! floating point division
   realRes = p/q  
   intRes = i/j
   
   print *, realRes
   print *, intRes
   
end program division

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

0.666666687    
0

Tipo Complexo

Isso é usado para armazenar números complexos. Um número complexo possui duas partes: a parte real e a parte imaginária. Duas unidades de armazenamento numérico consecutivas armazenam essas duas partes.

Por exemplo, o número complexo (3,0, -5,0) é igual a 3,0 - 5,0i

A função genérica cmplx()cria um número complexo. Ele produz um resultado cujas partes reais e imaginárias são de precisão única, independentemente do tipo dos argumentos de entrada.

program createComplex
implicit none

   integer :: i = 10
   real :: x = 5.17
   print *, cmplx(i, x)
   
end program createComplex

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

(10.0000000, 5.17000008)

O programa a seguir demonstra aritmética de números complexos -

program ComplexArithmatic
implicit none

   complex, parameter :: i = (0, 1)   ! sqrt(-1)   
   complex :: x, y, z 
   
   x = (7, 8); 
   y = (5, -7)   
   write(*,*) i * x * y
   
   z = x + y
   print *, "z = x + y = ", z
   
   z = x - y
   print *, "z = x - y = ", z 
   
   z = x * y
   print *, "z = x * y = ", z 
   
   z = x / y
   print *, "z = x / y = ", z 
   
end program ComplexArithmatic

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

(9.00000000, 91.0000000)
z = x + y = (12.0000000, 1.00000000)
z = x - y = (2.00000000, 15.0000000)
z = x * y = (91.0000000, -9.00000000)
z = x / y = (-0.283783793, 1.20270276)

Alcance, precisão e tamanho dos números

O intervalo de números inteiros, a precisão e o tamanho dos números de ponto flutuante dependem do número de bits alocados para o tipo de dados específico.

A tabela a seguir exibe o número de bits e intervalo para inteiros -

Número de bits Valor máximo Razão
64 9.223.372.036.854.774.807 (2 ** 63) -1
32 2.147.483.647 (2 ** 31) -1

A tabela a seguir exibe o número de bits, o menor e o maior valor e a precisão dos números reais.

Número de bits Maior valor Menor valor Precisão
64 0,8E + 308 0,5E-308 15–18
32 1.7E + 38 0,3E – 38 6-9

Os exemplos a seguir demonstram isso -

program rangePrecision
implicit none

   real:: x, y, z
   x = 1.5e+40
   y = 3.73e+40
   z = x * y 
   print *, z
   
end program rangePrecision

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

x = 1.5e+40
          1
Error : Real constant overflows its kind at (1)
main.f95:5.12:

y = 3.73e+40
           1
Error : Real constant overflows its kind at (1)

Agora vamos usar um número menor -

program rangePrecision
implicit none

   real:: x, y, z
   x = 1.5e+20
   y = 3.73e+20
   z = x * y 
   print *, z
   
   z = x/y
   print *, z
   
end program rangePrecision

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Infinity
0.402144760

Agora vamos observar o underflow -

program rangePrecision
implicit none

   real:: x, y, z
   x = 1.5e-30
   y = 3.73e-60
   z = x * y 
   print *, z
   
   z = x/y
   print *, z

end program rangePrecision

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

y = 3.73e-60
           1
Warning : Real constant underflows its kind at (1)

Executing the program....
$demo 

0.00000000E+00
Infinity

O especificador de tipo

Na programação científica, muitas vezes é necessário saber o alcance e a precisão dos dados da plataforma de hardware na qual o trabalho está sendo feito.

A função intrínseca kind() permite consultar os detalhes das representações de dados do hardware antes de executar um programa.

program kindCheck
implicit none
   
   integer :: i 
   real :: r 
   complex :: cp 
   print *,' Integer ', kind(i) 
   print *,' Real ', kind(r) 
   print *,' Complex ', kind(cp) 
   
end program kindCheck

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Integer 4
Real 4
Complex 4

Você também pode verificar o tipo de todos os tipos de dados -

program checkKind
implicit none

   integer :: i 
   real :: r 
   character :: c 
   logical :: lg 
   complex :: cp 
   
   print *,' Integer ', kind(i) 
   print *,' Real ', kind(r) 
   print *,' Complex ', kind(cp)
   print *,' Character ', kind(c) 
   print *,' Logical ', kind(lg)
   
end program checkKind

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Integer 4
Real 4
Complex 4
Character 1
Logical 4

A linguagem Fortran pode tratar os caracteres como caracteres únicos ou sequências contíguas.

Os caracteres podem ser qualquer símbolo retirado do conjunto de caracteres básico, ou seja, das letras, os dígitos decimais, o sublinhado e 21 caracteres especiais.

Uma constante de caractere é uma cadeia de caracteres de valor fixo.

O tipo de dados intrínseco characterarmazena caracteres e strings. O comprimento da string pode ser especificado porlenespecificador. Se nenhum comprimento for especificado, é 1. Você pode referir-se a caracteres individuais em uma string referindo-se por posição; o caractere mais à esquerda está na posição 1.

Declaração de Personagem

Declarar dados de tipo de caractere é igual a outras variáveis ​​-

type-specifier :: variable_name

Por exemplo,

character :: reply, sex

você pode atribuir um valor como,

reply = ‘N’ 
sex = ‘F’

O exemplo a seguir demonstra a declaração e o uso do tipo de dados de caractere -

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   
   title = 'Mr. ' 
   firstname = 'Rowan ' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Bean'
   
   print *, 'Here is ', title, firstname, surname
   print *, greetings
   
end program hello

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Here is Mr. Rowan Atkinson       
A big hello from Mr. Bean

Concatenação de Personagens

O operador de concatenação // concatena caracteres.

O exemplo a seguir demonstra isso -

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25)::greetings
   
   title = 'Mr. ' 
   firstname = 'Rowan ' 
   surname = 'Atkinson'
   
   name = title//firstname//surname
   greetings = 'A big hello from Mr. Bean'
   
   print *, 'Here is ', name
   print *, greetings
   
end program hello

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Here is Mr.Rowan Atkinson       
A big hello from Mr.Bean

Algumas funções de personagem

A tabela a seguir mostra algumas funções de caractere comumente usadas junto com a descrição -

Sr. Não Descrição da função
1

len(string)

Ele retorna o comprimento de uma string de caracteres

2

index(string,sustring)

Ele encontra a localização de uma substring em outra string e retorna 0 se não for encontrada.

3

achar(int)

Ele converte um número inteiro em um caractere

4

iachar(c)

Ele converte um caractere em um inteiro

5

trim(string)

Ele retorna a string com os espaços em branco à direita removidos.

6

scan(string, chars)

Ele pesquisa a "string" da esquerda para a direita (a menos que back = .true.) Para a primeira ocorrência de qualquer caractere contido em "chars". Ele retorna um inteiro fornecendo a posição daquele caractere, ou zero se nenhum dos caracteres em "chars" for encontrado.

7

verify(string, chars)

Ele verifica a "string" da esquerda para a direita (a menos que back = .true.) Para a primeira ocorrência de qualquer caractere não contido em "chars". Ele retorna um inteiro fornecendo a posição desse caractere ou zero se apenas os caracteres em "chars" forem encontrados

8

adjustl(string)

Ele justifica à esquerda os caracteres contidos na "string"

9

adjustr(string)

Ele justifica à direita os caracteres contidos na "string"

10

len_trim(string)

Ele retorna um inteiro igual ao comprimento da "string" (len (string)) menos o número de espaços em branco à direita

11

repeat(string,ncopy)

Ele retorna uma string com comprimento igual a "ncopy" vezes o comprimento de "string" e contendo cópias concatenadas de "ncopy" de "string"

Exemplo 1

Este exemplo mostra o uso do index função -

program testingChars
implicit none

   character (80) :: text 
   integer :: i 
   
   text = 'The intrinsic data type character stores characters and   strings.'
   i=index(text,'character') 
   
   if (i /= 0) then
      print *, ' The word character found at position ',i 
      print *, ' in text: ', text 
   end if
   
end program testingChars

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

The word character found at position 25
in text : The intrinsic data type character stores characters and strings.

Exemplo 2

Este exemplo demonstra o uso do trim função -

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   
   print *, 'Here is', title, firstname, surname
   print *, 'Here is', trim(title),' ',trim(firstname),' ', trim(surname)
   
end program hello

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Here isMr.   Rowan          Atkinson       
 Here isMr. Rowan Atkinson

Exemplo 3

Este exemplo demonstra o uso de achar função -

program testingChars
implicit none

   character:: ch
   integer:: i
   
   do i = 65, 90
      ch = achar(i)
      print*, i, ' ', ch
   end do
   
end program testingChars

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

65  A
66  B
67  C
68  D
69  E
70  F
71  G
72  H
73  I
74  J
75  K
76  L
77  M
78  N
79  O
80  P
81  Q
82  R
83  S
84  T
85  U
86  V
87  W
88  X
89  Y
90  Z

Verificando a ordem lexical dos personagens

As funções a seguir determinam a sequência lexical de caracteres -

Sr. Não Descrição da função
1

lle(char, char)

Compara se o primeiro caractere é lexicamente menor ou igual ao segundo

2

lge(char, char)

Compara se o primeiro caractere é lexicamente maior ou igual ao segundo

3

lgt(char, char)

Compara se o primeiro caractere é lexicamente maior que o segundo

4

llt(char, char)

Compara se o primeiro caractere é lexicamente menor que o segundo

Example 4

A função a seguir demonstra o uso -

program testingChars
implicit none

   character:: a, b, c
   a = 'A'
   b = 'a'
   c = 'B'
   
   if(lgt(a,b)) then
      print *, 'A is lexically greater than a'
   else
      print *, 'a is lexically greater than A'
   end if
   
   if(lgt(a,c)) then
      print *, 'A is lexically greater than B'
   else
      print *, 'B is lexically greater than A'
   end if  
   
   if(llt(a,b)) then
      print *, 'A is lexically less than a'
   end if
   
   if(llt(a,c)) then
      print *, 'A is lexically less than B'
   end if
   
end program testingChars

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

a is lexically greater than A
B is lexically greater than A
A is lexically less than a
A is lexically less than B

A linguagem Fortran pode tratar os caracteres como caracteres únicos ou sequências contíguas.

Uma sequência de caracteres pode ter apenas um caractere de comprimento ou pode até ter comprimento zero. No Fortran, as constantes de caracteres são fornecidas entre um par de aspas duplas ou simples.

O tipo de dados intrínseco characterarmazena caracteres e strings. O comprimento da string pode ser especificado porlen specifier. Se nenhum comprimento for especificado, é 1. Você pode referir-se a caracteres individuais em uma string referindo-se por posição; o caractere mais à esquerda está na posição 1.

Declaração de String

Declarar uma string é igual a outras variáveis ​​-

type-specifier :: variable_name

Por exemplo,

Character(len = 20) :: firstname, surname

você pode atribuir um valor como,

character (len = 40) :: name  
name = “Zara Ali”

O exemplo a seguir demonstra a declaração e o uso do tipo de dados de caractere -

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Beans'
   
   print *, 'Here is', title, firstname, surname
   print *, greetings
   
end program hello

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Here isMr.   Rowan          Atkinson       
A big hello from Mr. Bean

String Concatenation

O operador de concatenação // concatena strings.

O exemplo a seguir demonstra isso -

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25)::greetings
   
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   
   name = title//firstname//surname
   greetings = 'A big hello from Mr. Beans'
   
   print *, 'Here is', name
   print *, greetings
   
end program hello

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Here is Mr. Rowan Atkinson       
A big hello from Mr. Bean

Extraindo substrings

No Fortran, você pode extrair uma substring de uma string indexando a string, fornecendo o índice inicial e final da substring em um par de colchetes. Isso é chamado de especificador de extensão.

O exemplo a seguir mostra como extrair a substring 'world' da string 'hello world' -

program subString

   character(len = 11)::hello
   hello = "Hello World"
   print*, hello(7:11)
   
end program subString

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

World

Exemplo

O exemplo a seguir usa o date_and_timefunção para fornecer a string de data e hora. Usamos especificadores de extensão para extrair as informações de ano, data, mês, hora, minutos e segundos separadamente.

program  datetime
implicit none

   character(len = 8) :: dateinfo ! ccyymmdd
   character(len = 4) :: year, month*2, day*2

   character(len = 10) :: timeinfo ! hhmmss.sss
   character(len = 2)  :: hour, minute, second*6

   call  date_and_time(dateinfo, timeinfo)

   !  let’s break dateinfo into year, month and day.
   !  dateinfo has a form of ccyymmdd, where cc = century, yy = year
   !  mm = month and dd = day

   year  = dateinfo(1:4)
   month = dateinfo(5:6)
   day   = dateinfo(7:8)

   print*, 'Date String:', dateinfo
   print*, 'Year:', year
   print *,'Month:', month
   print *,'Day:', day

   !  let’s break timeinfo into hour, minute and second.
   !  timeinfo has a form of hhmmss.sss, where h = hour, m = minute
   !  and s = second

   hour   = timeinfo(1:2)
   minute = timeinfo(3:4)
   second = timeinfo(5:10)

   print*, 'Time String:', timeinfo
   print*, 'Hour:', hour
   print*, 'Minute:', minute
   print*, 'Second:', second   
   
end program  datetime

Quando você compila e executa o programa acima, ele fornece informações detalhadas de data e hora -

Date String: 20140803
Year: 2014
Month: 08
Day: 03
Time String: 075835.466
Hour: 07
Minute: 58
Second: 35.466

Corte de cordas

o trim função recebe uma string e retorna a string de entrada após remover todos os espaços em branco à direita.

Exemplo

program trimString
implicit none

   character (len = *), parameter :: fname="Susanne", sname="Rizwan"
   character (len = 20) :: fullname 
   
   fullname = fname//" "//sname !concatenating the strings
   
   print*,fullname,", the beautiful dancer from the east!"
   print*,trim(fullname),", the beautiful dancer from the east!"
   
end program trimString

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Susanne Rizwan      , the beautiful dancer from the east!
 Susanne Rizwan, the beautiful dancer from the east!

Ajuste Esquerdo e Direito de Strings

A função adjustl pega uma string e a retorna removendo os espaços em branco à esquerda e acrescentando-os como espaços em branco à direita.

A função adjustr pega uma string e a retorna removendo os espaços em branco à direita e acrescentando-os como espaços em branco à esquerda.

Exemplo

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25):: greetings
   
   title = 'Mr. ' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Beans'
   
   name = adjustl(title)//adjustl(firstname)//adjustl(surname)
   print *, 'Here is', name
   print *, greetings
   
   name = adjustr(title)//adjustr(firstname)//adjustr(surname)
   print *, 'Here is', name
   print *, greetings
   
   name = trim(title)//trim(firstname)//trim(surname)
   print *, 'Here is', name
   print *, greetings
   
end program hello

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Here is Mr. Rowan  Atkinson           
A big hello from Mr. Bean
Here is Mr. Rowan Atkinson    
A big hello from Mr. Bean
Here is Mr.RowanAtkinson                        
A big hello from Mr. Bean

Procurando por uma substring em uma string

A função de índice pega duas strings e verifica se a segunda string é uma substring da primeira string. Se o segundo argumento for uma substring do primeiro argumento, ele retornará um inteiro que é o índice inicial da segunda string na primeira string, caso contrário, ele retornará zero.

Exemplo

program hello
implicit none

   character(len=30) :: myString
   character(len=10) :: testString
   
   myString = 'This is a test'
   testString = 'test'
   
   if(index(myString, testString) == 0)then
      print *, 'test is not found'
   else
      print *, 'test is found at index: ', index(myString, testString)
   end if
   
end program hello

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

test is found at index: 11

Os arrays podem armazenar uma coleção sequencial de tamanho fixo de elementos do mesmo tipo. Uma matriz é usada para armazenar uma coleção de dados, mas geralmente é mais útil pensar em uma matriz como uma coleção de variáveis ​​do mesmo tipo.

Todos os arrays consistem em locais de memória contíguos. O endereço mais baixo corresponde ao primeiro elemento e o endereço mais alto ao último elemento.

Números (1) Números (2) Números (3) Números (4)

Os arrays podem ser unidimensionais (como vetores), bidimensionais (como matrizes) e o Fortran permite que você crie arrays de até 7 dimensões.

Declaração de matrizes

Arrays são declarados com o dimension atributo.

Por exemplo, para declarar uma matriz unidimensional chamada número, de números reais contendo 5 elementos, você escreve,

real, dimension(5) :: numbers

Os elementos individuais dos arrays são referenciados especificando seus subscritos. O primeiro elemento de uma matriz possui um subscrito de um. Os números da matriz contêm cinco variáveis ​​reais - números (1), números (2), números (3), números (4) e números (5).

Para criar uma matriz bidimensional 5 x 5 de inteiros denominados matriz, você escreve -

integer, dimension (5,5) :: matrix

Você também pode declarar uma matriz com algum limite inferior explícito, por exemplo -

real, dimension(2:6) :: numbers
integer, dimension (-3:2,0:4) :: matrix

Atribuição de Valores

Você pode atribuir valores a membros individuais, como,

numbers(1) = 2.0

ou você pode usar um loop,

do i  =1,5
   numbers(i) = i * 2.0
end do

Elementos de matriz unidimensional podem receber valores diretamente atribuídos usando um símbolo de mão curta, chamado construtor de matriz, como,

numbers = (/1.5, 3.2,4.5,0.9,7.2 /)

please note that there are no spaces allowed between the brackets ‘( ‘and the back slash ‘/’

Exemplo

O exemplo a seguir demonstra os conceitos discutidos acima.

program arrayProg

   real :: numbers(5) !one dimensional integer array
   integer :: matrix(3,3), i , j !two dimensional real array
   
   !assigning some values to the array numbers
   do i=1,5
      numbers(i) = i * 2.0
   end do
   
   !display the values
   do i = 1, 5
      Print *, numbers(i)
   end do
   
   !assigning some values to the array matrix
   do i=1,3
      do j = 1, 3
         matrix(i, j) = i+j
      end do
   end do
   
   !display the values
   do i=1,3
      do j = 1, 3
         Print *, matrix(i,j)
      end do
   end do
   
   !short hand assignment
   numbers = (/1.5, 3.2,4.5,0.9,7.2 /)
   
   !display the values
   do i = 1, 5
      Print *, numbers(i)
   end do
   
end program arrayProg

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

2.00000000    
 4.00000000    
 6.00000000    
 8.00000000    
 10.0000000    
         2
         3
         4
         3
         4
         5
         4
         5
         6
 1.50000000    
 3.20000005    
 4.50000000    
0.899999976    
 7.19999981

Alguns termos relacionados à matriz

A tabela a seguir fornece alguns termos relacionados à matriz -

Prazo Significado
Classificação É o número de dimensões que um array possui. Por exemplo, para a matriz denominada matriz, classificação é 2, e para a matriz denominada números, classificação é 1.
Extensão É o número de elementos ao longo de uma dimensão. Por exemplo, os números da matriz possuem extensão 5 e a matriz denominada matriz possui extensão 3 em ambas as dimensões.
Forma A forma de uma matriz é uma matriz inteira unidimensional, contendo o número de elementos (a extensão) em cada dimensão. Por exemplo, para a matriz da matriz, a forma é (3, 3) e os números da matriz é (5).
Tamanho É o número de elementos que um array contém. Para a matriz da matriz, é 9, e para os números da matriz, é 5.

Passando Arrays para Procedimentos

Você pode passar uma matriz para um procedimento como um argumento. O exemplo a seguir demonstra o conceito -

program arrayToProcedure      
implicit none      

   integer, dimension (5) :: myArray  
   integer :: i
   
   call fillArray (myArray)      
   call printArray(myArray)
   
end program arrayToProcedure


subroutine fillArray (a)      
implicit none      

   integer, dimension (5), intent (out) :: a
   
   ! local variables     
   integer :: i     
   do i = 1, 5         
      a(i) = i      
   end do  
   
end subroutine fillArray 


subroutine printArray(a)

   integer, dimension (5) :: a  
   integer::i
   
   do i = 1, 5
      Print *, a(i)
   end do
   
end subroutine printArray

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

1
2
3
4
5

No exemplo acima, a sub-rotina fillArray e printArray só podem ser chamados com arrays com dimensão 5. No entanto, para escrever sub-rotinas que podem ser usadas para arrays de qualquer tamanho, você pode reescrevê-lo usando a seguinte técnica -

program arrayToProcedure      
implicit  none    

   integer, dimension (10) :: myArray  
   integer :: i
   
   interface 
      subroutine fillArray (a)
         integer, dimension(:), intent (out) :: a 
         integer :: i         
      end subroutine fillArray      

      subroutine printArray (a)
         integer, dimension(:) :: a 
         integer :: i         
      end subroutine printArray   
   end interface 
   
   call fillArray (myArray)      
   call printArray(myArray)
   
end program arrayToProcedure


subroutine fillArray (a)      
implicit none      
   integer,dimension (:), intent (out) :: a      
   
   ! local variables     
   integer :: i, arraySize  
   arraySize = size(a)
   
   do i = 1, arraySize         
      a(i) = i      
   end do  
   
end subroutine fillArray 


subroutine printArray(a)
implicit none

   integer,dimension (:) :: a  
   integer::i, arraySize
   arraySize = size(a)
   
   do i = 1, arraySize
     Print *, a(i)
   end do
   
end subroutine printArray

Observe que o programa está usando o size função para obter o tamanho da matriz.

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

1
2
3
4
5
6
7
8
9
10

Seções de matriz

Até agora nos referimos a todo o array. Fortran fornece uma maneira fácil de referir vários elementos, ou uma seção de um array, usando uma única instrução.

Para acessar uma seção de matriz, você precisa fornecer os limites inferior e superior da seção, bem como uma passada (incremento), para todas as dimensões. Esta notação é chamada desubscript triplet:

array ([lower]:[upper][:stride], ...)

Quando nenhum limite inferior e superior é mencionado, o padrão é a extensão que você declarou e o valor da passada é 1.

O exemplo a seguir demonstra o conceito -

program arraySubsection

   real, dimension(10) :: a, b
   integer:: i, asize, bsize
   
   a(1:7) = 5.0 ! a(1) to a(7) assigned 5.0
   a(8:) = 0.0  ! rest are 0.0 
   b(2:10:2) = 3.9
   b(1:9:2) = 2.5
   
   !display
   asize = size(a)
   bsize = size(b)
   
   do i = 1, asize
      Print *, a(i)
   end do
   
   do i = 1, bsize
      Print *, b(i)
   end do
   
end program arraySubsection

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
0.00000000E+00
0.00000000E+00
0.00000000E+00
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010

Funções intrínsecas de matriz

O Fortran 90/95 fornece vários procedimentos intrínsecos. Eles podem ser divididos em 7 categorias.

  • Multiplicação de vetores e matrizes

  • Reduction

  • Inquiry

  • Construction

  • Reshape

  • Manipulation

  • Location

UMA dynamic array é um array cujo tamanho não é conhecido no momento da compilação, mas será conhecido no momento da execução.

Arrays dinâmicos são declarados com o atributo allocatable.

Por exemplo,

real, dimension (:,:), allocatable :: darray

A classificação da matriz, ou seja, as dimensões devem ser mencionadas, no entanto, para alocar memória a tal matriz, você usa o allocate função.

allocate ( darray(s1,s2) )

Depois que o array é usado, no programa, a memória criada deve ser liberada usando o deallocate função

deallocate (darray)

Exemplo

O exemplo a seguir demonstra os conceitos discutidos acima.

program dynamic_array 
implicit none 

   !rank is 2, but size not known   
   real, dimension (:,:), allocatable :: darray    
   integer :: s1, s2     
   integer :: i, j     
   
   print*, "Enter the size of the array:"     
   read*, s1, s2      
   
   ! allocate memory      
   allocate ( darray(s1,s2) )      
   
   do i = 1, s1           
      do j = 1, s2                
         darray(i,j) = i*j               
         print*, "darray(",i,",",j,") = ", darray(i,j)           
      end do      
   end do      
   
   deallocate (darray)  
end program dynamic_array

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

Enter the size of the array: 3,4
darray( 1 , 1 ) = 1.00000000    
darray( 1 , 2 ) = 2.00000000    
darray( 1 , 3 ) = 3.00000000    
darray( 1 , 4 ) = 4.00000000    
darray( 2 , 1 ) = 2.00000000    
darray( 2 , 2 ) = 4.00000000    
darray( 2 , 3 ) = 6.00000000    
darray( 2 , 4 ) = 8.00000000    
darray( 3 , 1 ) = 3.00000000    
darray( 3 , 2 ) = 6.00000000    
darray( 3 , 3 ) = 9.00000000    
darray( 3 , 4 ) = 12.0000000

Declaração de Uso de Dados

o data instrução pode ser usada para inicializar mais de uma matriz ou para a inicialização da seção da matriz.

A sintaxe da declaração de dados é -

data variable / list / ...

Exemplo

O exemplo a seguir demonstra o conceito -

program dataStatement
implicit none

   integer :: a(5), b(3,3), c(10),i, j
   data a /7,8,9,10,11/ 
   
   data b(1,:) /1,1,1/ 
   data b(2,:)/2,2,2/ 
   data b(3,:)/3,3,3/ 
   data (c(i),i = 1,10,2) /4,5,6,7,8/ 
   data (c(i),i = 2,10,2)/5*2/
   
   Print *, 'The A array:'
   do j = 1, 5                
      print*, a(j)           
   end do 
   
   Print *, 'The B array:'
   do i = lbound(b,1), ubound(b,1)
      write(*,*) (b(i,j), j = lbound(b,2), ubound(b,2))
   end do

   Print *, 'The C array:' 
   do j = 1, 10                
      print*, c(j)           
   end do      
   
end program dataStatement

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

The A array:
           7
           8
           9
          10
          11
 The B array:
           1           1           1
           2           2           2
           3           3           3
 The C array:
           4
           2
           5
           2
           6
           2
           7
           2
           8
           2

Declaração de uso de Where

o whereinstrução permite que você use alguns elementos de uma matriz em uma expressão, dependendo do resultado de alguma condição lógica. Permite a execução da expressão, em um elemento, se a condição dada for verdadeira.

Exemplo

O exemplo a seguir demonstra o conceito -

program whereStatement
implicit none

   integer :: a(3,5), i , j
   
   do i = 1,3
      do j = 1, 5                
         a(i,j) = j-i          
      end do 
   end do
   
   Print *, 'The A array:'
   
   do i = lbound(a,1), ubound(a,1)
      write(*,*) (a(i,j), j = lbound(a,2), ubound(a,2))
   end do
   
   where( a<0 ) 
      a = 1 
   elsewhere
      a = 5
   end where
  
   Print *, 'The A array:'
   do i = lbound(a,1), ubound(a,1)
      write(*,*) (a(i,j), j = lbound(a,2), ubound(a,2))
   end do   
   
end program whereStatement

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

The A array:
           0           1           2           3           4
          -1           0           1           2           3
          -2          -1           0           1           2
 The A array:
           5           5           5           5           5
           1           5           5           5           5
           1           1           5           5           5

Fortran permite definir tipos de dados derivados. Um tipo de dados derivado também é chamado de estrutura e pode consistir em objetos de dados de diferentes tipos.

Os tipos de dados derivados são usados ​​para representar um registro. Por exemplo, você deseja controlar seus livros em uma biblioteca, você pode querer controlar os seguintes atributos sobre cada livro -

  • Title
  • Author
  • Subject
  • ID do livro

Definindo um tipo de dado derivado

Para definir um dado derivado type, o tipo e end typedeclarações são usadas. . A instrução type define um novo tipo de dados, com mais de um membro para seu programa. O formato da declaração de tipo é este -

type type_name      
   declarations
end type

Esta é a maneira como você declararia a estrutura do livro -

type Books
   character(len = 50) :: title
   character(len = 50) :: author
   character(len = 150) :: subject
   integer :: book_id
end type Books

Acessando membros da estrutura

Um objeto de um tipo de dados derivado é chamado de estrutura.

Uma estrutura do tipo Books pode ser criada em uma declaração de tipo como -

type(Books) :: book1

Os componentes da estrutura podem ser acessados ​​usando o caractere seletor de componentes (%) -

book1%title = "C Programming"
book1%author = "Nuha Ali"
book1%subject = "C Programming Tutorial"
book1%book_id = 6495407

Note that there are no spaces before and after the % symbol.

Exemplo

O programa a seguir ilustra os conceitos acima -

program deriveDataType

   !type declaration
   type Books
      character(len = 50) :: title
      character(len = 50) :: author
      character(len = 150) :: subject
      integer :: book_id
   end type Books
   
   !declaring type variables
   type(Books) :: book1 
   type(Books) :: book2 
   
   !accessing the components of the structure
   
   book1%title = "C Programming"
   book1%author = "Nuha Ali"
   book1%subject = "C Programming Tutorial"
   book1%book_id = 6495407 
   
   book2%title = "Telecom Billing"
   book2%author = "Zara Ali"
   book2%subject = "Telecom Billing Tutorial"
   book2%book_id = 6495700
  
   !display book info
   
   Print *, book1%title 
   Print *, book1%author 
   Print *, book1%subject 
   Print *, book1%book_id  
   
   Print *, book2%title 
   Print *, book2%author 
   Print *, book2%subject 
   Print *, book2%book_id  

end program deriveDataType

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

C Programming                                     
 Nuha Ali                                          
 C Programming Tutorial            
   6495407
 Telecom Billing                                   
 Zara Ali                                          
 Telecom Billing Tutorial            
   6495700

Matriz de Estruturas

Você também pode criar matrizes de um tipo derivado -

type(Books), dimension(2) :: list

Elementos individuais da matriz podem ser acessados ​​como -

list(1)%title = "C Programming"
list(1)%author = "Nuha Ali"
list(1)%subject = "C Programming Tutorial"
list(1)%book_id = 6495407

O programa a seguir ilustra o conceito -

program deriveDataType

   !type declaration
   type Books
      character(len = 50) :: title
      character(len = 50) :: author
      character(len = 150) :: subject
      integer :: book_id
   end type Books
   
   !declaring array of books
   type(Books), dimension(2) :: list 
    
   !accessing the components of the structure
   
   list(1)%title = "C Programming"
   list(1)%author = "Nuha Ali"
   list(1)%subject = "C Programming Tutorial"
   list(1)%book_id = 6495407 
   
   list(2)%title = "Telecom Billing"
   list(2)%author = "Zara Ali"
   list(2)%subject = "Telecom Billing Tutorial"
   list(2)%book_id = 6495700
  
   !display book info
   
   Print *, list(1)%title 
   Print *, list(1)%author 
   Print *, list(1)%subject 
   Print *, list(1)%book_id  
   
   Print *, list(1)%title 
   Print *, list(2)%author 
   Print *, list(2)%subject 
   Print *, list(2)%book_id  

end program deriveDataType

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

C Programming                                     
Nuha Ali                                          
C Programming Tutorial               
   6495407
C Programming                                     
Zara Ali                                          
Telecom Billing Tutorial                                      
   6495700

Na maioria das linguagens de programação, uma variável de ponteiro armazena o endereço de memória de um objeto. No entanto, no Fortran, um ponteiro é um objeto de dados que possui mais funcionalidades do que apenas armazenar o endereço da memória. Ele contém mais informações sobre um determinado objeto, como tipo, classificação, extensões e endereço de memória.

Um ponteiro é associado a um destino por alocação ou atribuição de ponteiro.

Declaração de uma variável de ponteiro

Uma variável de ponteiro é declarada com o atributo ponteiro.

Os exemplos a seguir mostram a declaração de variáveis ​​de ponteiro -

integer, pointer :: p1 ! pointer to integer  
real, pointer, dimension (:) :: pra ! pointer to 1-dim real array  
real, pointer, dimension (:,:) :: pra2 ! pointer to 2-dim real array

Um ponteiro pode apontar para -

  • Uma área de memória alocada dinamicamente.

  • Um objeto de dados do mesmo tipo do ponteiro, com o target atributo.

Alocando espaço para um ponteiro

o allocateinstrução permite que você aloque espaço para um objeto de ponteiro. Por exemplo -

program pointerExample
implicit none

   integer, pointer :: p1
   allocate(p1)
   
   p1 = 1
   Print *, p1
   
   p1 = p1 + 4
   Print *, p1
   
end program pointerExample

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

1
5

Você deve esvaziar o espaço de armazenamento alocado pelo deallocate declaração quando não é mais necessária e evita o acúmulo de espaço de memória não utilizado e inutilizável.

Metas e associação

Um alvo é outra variável normal, com espaço reservado para ele. Uma variável de destino deve ser declarada com otarget atributo.

Você associa uma variável de ponteiro a uma variável de destino usando o operador de associação (=>).

Vamos reescrever o exemplo anterior, para demonstrar o conceito -

program pointerExample
implicit none

   integer, pointer :: p1
   integer, target :: t1 
   
   p1=>t1
   p1 = 1
   
   Print *, p1
   Print *, t1
   
   p1 = p1 + 4
   
   Print *, p1
   Print *, t1
   
   t1 = 8
   
   Print *, p1
   Print *, t1
   
end program pointerExample

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

1
1
5
5
8
8

Um ponteiro pode ser -

  • Undefined
  • Associated
  • Disassociated

No programa acima, temos associatedo ponteiro p1, com o alvo t1, usando o operador =>. A função associada testa o status de associação de um ponteiro.

o nullify declaração desassocia um ponteiro de um destino.

Nullify não esvazia os alvos, pois pode haver mais de um ponteiro apontando para o mesmo alvo. No entanto, esvaziar o ponteiro implica também na anulação.

Exemplo 1

O exemplo a seguir demonstra os conceitos -

program pointerExample
implicit none

   integer, pointer :: p1
   integer, target :: t1 
   integer, target :: t2
   
   p1=>t1
   p1 = 1
   
   Print *, p1
   Print *, t1
   
   p1 = p1 + 4
   Print *, p1
   Print *, t1
   
   t1 = 8
   Print *, p1
   Print *, t1
   
   nullify(p1)
   Print *, t1
   
   p1=>t2
   Print *, associated(p1)
   Print*, associated(p1, t1)
   Print*, associated(p1, t2)
   
   !what is the value of p1 at present
   Print *, p1
   Print *, t2
   
   p1 = 10
   Print *, p1
   Print *, t2
   
end program pointerExample

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

1
1
5
5
8
8
8
T
F
T
952754640
952754640
10
10

Observe que cada vez que você executa o código, os endereços de memória serão diferentes.

Exemplo 2

program pointerExample
implicit none

   integer, pointer :: a, b
   integer, target :: t
   integer :: n
   
   t = 1
   a => t
   t = 2
   b => t
   n = a + b
   
   Print *, a, b, t, n 
   
end program pointerExample

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

2  2  2  4

Vimos até agora que podemos ler dados do teclado usando o read * declaração, e exibir a saída na tela usando o print*declaração, respectivamente. Esta forma de entrada-saída éfree format I / O, e é chamado list-directed entrada-saída.

O I / O simples de formato livre tem a forma -

read(*,*) item1, item2, item3...
print *, item1, item2, item3
write(*,*) item1, item2, item3...

No entanto, a E / S formatada oferece mais flexibilidade sobre a transferência de dados.

Saída formatada de entrada

A saída de entrada formatada tem a seguinte sintaxe -

read fmt, variable_list 
print fmt, variable_list 
write fmt, variable_list

Onde,

  • fmt é a especificação do formato

  • lista de variáveis ​​é uma lista das variáveis ​​a serem lidas do teclado ou escritas na tela

A especificação de formato define a maneira como os dados formatados são exibidos. Consiste em uma string, contendo uma lista deedit descriptors em parênteses.

A edit descriptor especifica o formato exato, por exemplo, largura, dígitos após a vírgula decimal etc., no qual os caracteres e números são exibidos.

Por exemplo

Print "(f6.3)", pi

A tabela a seguir descreve os descritores -

Descritor Descrição Exemplo
Eu

Isso é usado para saída de inteiros. Ele assume a forma 'rIw.m', onde os significados de r, w e m são fornecidos na tabela abaixo. Os valores inteiros são justificados à direita em seus campos. Se a largura do campo não for grande o suficiente para acomodar um número inteiro, o campo será preenchido com asteriscos.

imprimir "(3i5)", i, j, k
F

Isso é usado para saída de número real. Ele assume a forma 'rFw.d', onde os significados de r, w e d são fornecidos na tabela abaixo. Os valores reais são justificados corretamente em seus campos. Se a largura do campo não for grande o suficiente para acomodar o número real, o campo será preenchido com asteriscos.

imprimir "(f12.3)", pi
E

Isso é usado para saída real em notação exponencial. A declaração do descritor 'E' assume a forma 'rEw.d' onde os significados de r, w e d são fornecidos na tabela abaixo. Os valores reais são justificados corretamente em seus campos. Se a largura do campo não for grande o suficiente para acomodar o número real, o campo será preenchido com asteriscos.

Observe que, para imprimir um número real com três casas decimais, é necessária uma largura de campo de pelo menos dez. Um para o sinal da mantissa, dois para o zero, quatro para a mantissa e dois para o próprio expoente. Em geral, w ≥ d + 7.

imprimir "(e10.3)", 123456.0 dá '0,123e + 06'
ES

Isso é usado para saída real (notação científica). Isso assume a forma 'rESw.d', onde os significados de r, w e d são fornecidos na tabela abaixo. O descritor 'E' descrito acima difere ligeiramente da bem conhecida 'notação científica'. A notação científica tem a mantissa na faixa de 1,0 a 10,0, ao contrário do descritor E, que tem a mantissa na faixa de 0,1 a 1,0. Os valores reais são justificados corretamente em seus campos. Se a largura do campo não for grande o suficiente para acomodar o número real, o campo será preenchido com asteriscos. Aqui também, o campo de largura deve satisfazer a expressão w ≥ d + 7

imprimir "(es10.3)", 123456.0 dá '1.235e + 05'
UMA

Isso é usado para saída de caracteres. Este assume a forma 'rAw' onde os significados de r e w são dados na tabela abaixo. Os tipos de caracteres são justificados corretamente em seus campos. Se a largura do campo não for grande o suficiente para acomodar a seqüência de caracteres, o campo será preenchido com os primeiros caracteres 'w' da seqüência.

imprimir "(a10)", str
X

Isso é usado para saída de espaço. Isso assume a forma 'nX', onde 'n' é o número de espaços desejados.

imprimir "(5x, a10)", str
/

Descritor de barra - usado para inserir linhas em branco. Isso assume a forma '/' e força a próxima saída de dados a estar em uma nova linha.

imprimir "(/, 5x, a10)", str

Os seguintes símbolos são usados ​​com os descritores de formato -

Sr. Não Símbolo e Descrição
1

c

Número da coluna

2

d

Número de dígitos à direita da casa decimal para entrada ou saída real

3

m

Número mínimo de dígitos a serem exibidos

4

n

Número de espaços para pular

5

r

Contagem de repetição - o número de vezes para usar um descritor ou grupo de descritores

6

w

Largura do campo - o número de caracteres a serem usados ​​para a entrada ou saída

Exemplo 1

program printPi

   pi = 3.141592653589793238 
   
   Print "(f6.3)", pi 
   Print "(f10.7)", pi
   Print "(f20.15)", pi 
   Print "(e16.4)", pi/100 
   
end program printPi

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

3.142
3.1415927
3.141592741012573
0.3142E-01

Exemplo 2

program printName
implicit none

   character (len = 15) :: first_name
   print *,' Enter your first name.' 
   print *,' Up to 20 characters, please'
   
   read *,first_name 
   print "(1x,a)",first_name
   
end program printName

Quando o código acima é compilado e executado, ele produz o seguinte resultado: (suponha que o usuário insira o nome Zara)

Enter your first name.
Up to 20 characters, please
Zara

Exemplo 3

program formattedPrint
implicit none

   real :: c = 1.2786456e-9, d = 0.1234567e3 
   integer :: n = 300789, k = 45, i = 2
   character (len=15) :: str="Tutorials Point"
   
   print "(i6)", k 
   print "(i6.3)", k 
   print "(3i10)", n, k, i 
   print "(i10,i3,i5)", n, k, i 
   print "(a15)",str 
   print "(f12.3)", d
   print "(e12.4)", c 
   print '(/,3x,"n = ",i6, 3x, "d = ",f7.4)', n, d
   
end program formattedPrint

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

45
045
300789 45  2
300789 45  2
Tutorials Point
123.457
0.1279E-08

n = 300789 d = *******

A declaração de formato

A instrução de formato permite que você misture e combine saída de caractere, inteiro e real em uma instrução. O exemplo a seguir demonstra isso -

program productDetails 
implicit none 

   character (len = 15) :: name
   integer :: id 
   real :: weight
   name = 'Ardupilot'
   id = 1
   weight = 0.08
   
   print *,' The product details are' 
   
   print 100
   100 format (7x,'Name:', 7x, 'Id:', 1x, 'Weight:')
   
   print 200, name, id, weight 
   200 format(1x, a, 2x, i3, 2x, f5.2) 
   
end program productDetails

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

The product details are
Name:       Id:    Weight:
Ardupilot   1       0.08

Fortran permite que você leia e grave dados em arquivos.

No último capítulo, você viu como ler e gravar dados no terminal. Neste capítulo, você estudará as funcionalidades de entrada e saída de arquivos fornecidas pelo Fortran.

Você pode ler e gravar em um ou mais arquivos. As instruções OPEN, WRITE, READ e CLOSE permitem que você faça isso.

Abrindo e fechando arquivos

Antes de usar um arquivo, você deve abri-lo. oopencomando é usado para abrir arquivos para leitura ou gravação. A forma mais simples do comando é -

open (unit = number, file = "name").

No entanto, a declaração aberta pode ter uma forma geral -

open (list-of-specifiers)

A tabela a seguir descreve os especificadores mais comumente usados ​​-

Sr. Não Especificador e descrição
1

[UNIT=] u

O número da unidade u pode ser qualquer número no intervalo 9-99 e indica o arquivo, você pode escolher qualquer número, mas cada arquivo aberto no programa deve ter um número exclusivo

2

IOSTAT= ios

É o identificador de status de E / S e deve ser uma variável inteira. Se a instrução de abertura for bem-sucedida, o valor ios retornado será zero, caso contrário, um valor diferente de zero.

3

ERR = err

É um rótulo para o qual o controle salta em caso de algum erro.

4

FILE = fname

Nome do arquivo, uma sequência de caracteres.

5

STATUS = sta

Mostra o status anterior do arquivo. Uma string de caracteres e pode ter um dos três valores NEW, OLD ou SCRATCH. Um arquivo de trabalho é criado e excluído quando fechado ou o programa termina.

6

ACCESS = acc

É o modo de acesso ao arquivo. Pode ter um dos dois valores, SEQUENTIAL ou DIRECT. O padrão é SEQUENCIAL.

7

FORM = frm

Fornece o status de formatação do arquivo. Pode ter um dos dois valores FORMATTED ou UNFORMATTED. O padrão é UNFORMATTED

8

RECL = rl

Ele especifica o comprimento de cada registro em um arquivo de acesso direto.

Após o arquivo ter sido aberto, ele é acessado por instruções de leitura e gravação. Uma vez feito isso, ele deve ser fechado usando oclose declaração.

A instrução close tem a seguinte sintaxe -

close ([UNIT = ]u[,IOSTAT = ios,ERR = err,STATUS = sta])

Observe que os parâmetros entre colchetes são opcionais.

Example

Este exemplo demonstra a abertura de um novo arquivo para gravar alguns dados no arquivo.

program outputdata   
implicit none

   real, dimension(100) :: x, y  
   real, dimension(100) :: p, q
   integer :: i  
   
   ! data  
   do i=1,100  
      x(i) = i * 0.1 
      y(i) = sin(x(i)) * (1-cos(x(i)/3.0))  
   end do  
   
   ! output data into a file 
   open(1, file = 'data1.dat', status = 'new')  
   do i=1,100  
      write(1,*) x(i), y(i)   
   end do  
   
   close(1) 
   
end program outputdata

Quando o código acima é compilado e executado, ele cria o arquivo data1.dat e grava os valores da matriz xey nele. E então fecha o arquivo.

Ler e gravar no arquivo

As instruções de leitura e gravação, respectivamente, são usadas para leitura e gravação em um arquivo, respectivamente.

Eles têm a seguinte sintaxe -

read ([UNIT = ]u, [FMT = ]fmt, IOSTAT = ios, ERR = err, END = s)
write([UNIT = ]u, [FMT = ]fmt, IOSTAT = ios, ERR = err, END = s)

A maioria dos especificadores já foi discutida na tabela acima.

O especificador END = s é um rótulo de instrução para onde o programa salta, quando atinge o fim do arquivo.

Example

Este exemplo demonstra como ler e gravar em um arquivo.

Neste programa, lemos a partir do arquivo, criamos no último exemplo, data1.dat, e o exibimos na tela.

program outputdata   
implicit none   

   real, dimension(100) :: x, y  
   real, dimension(100) :: p, q
   integer :: i  
   
   ! data  
   do i = 1,100  
      x(i) = i * 0.1 
      y(i) = sin(x(i)) * (1-cos(x(i)/3.0))  
   end do  
   
   ! output data into a file 
   open(1, file = 'data1.dat', status='new')  
   do i = 1,100  
      write(1,*) x(i), y(i)   
   end do  
   close(1) 

   ! opening the file for reading
   open (2, file = 'data1.dat', status = 'old')

   do i = 1,100  
      read(2,*) p(i), q(i)
   end do 
   
   close(2)
   
   do i = 1,100  
      write(*,*) p(i), q(i)
   end do 
   
end program outputdata

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

0.100000001  5.54589933E-05
0.200000003  4.41325130E-04
0.300000012  1.47636665E-03
0.400000006  3.45637114E-03
0.500000000  6.64328877E-03
0.600000024  1.12552457E-02
0.699999988  1.74576249E-02
0.800000012  2.53552198E-02
0.900000036  3.49861123E-02
1.00000000   4.63171229E-02
1.10000002   5.92407547E-02
1.20000005   7.35742599E-02
1.30000007   8.90605897E-02
1.39999998   0.105371222    
1.50000000   0.122110792    
1.60000002   0.138823599    
1.70000005   0.155002072    
1.80000007   0.170096487    
1.89999998   0.183526158    
2.00000000   0.194692180    
2.10000014   0.202990443    
2.20000005   0.207826138    
2.29999995   0.208628103    
2.40000010   0.204863414    
2.50000000   0.196052119    
2.60000014   0.181780845    
2.70000005   0.161716297    
2.79999995   0.135617107    
2.90000010   0.103344671    
3.00000000   6.48725405E-02
3.10000014   2.02930309E-02
3.20000005  -3.01767997E-02
3.29999995  -8.61928314E-02
3.40000010  -0.147283033    
3.50000000  -0.212848678    
3.60000014  -0.282169819    
3.70000005  -0.354410470    
3.79999995  -0.428629100    
3.90000010  -0.503789663    
4.00000000  -0.578774154    
4.09999990  -0.652400017    
4.20000029  -0.723436713    
4.30000019  -0.790623367    
4.40000010  -0.852691114    
4.50000000  -0.908382416    
4.59999990  -0.956472993    
4.70000029  -0.995793998    
4.80000019  -1.02525222    
4.90000010  -1.04385209    
5.00000000  -1.05071592    
5.09999990  -1.04510069    
5.20000029  -1.02641726    
5.30000019  -0.994243503    
5.40000010  -0.948338211    
5.50000000  -0.888650239    
5.59999990  -0.815326691    
5.70000029  -0.728716135    
5.80000019  -0.629372001    
5.90000010  -0.518047631    
6.00000000  -0.395693362    
6.09999990  -0.263447165    
6.20000029  -0.122622721    
6.30000019   2.53026206E-02
6.40000010   0.178709000    
6.50000000   0.335851669    
6.59999990   0.494883657    
6.70000029   0.653881252    
6.80000019   0.810866773    
6.90000010   0.963840425    
7.00000000   1.11080539    
7.09999990   1.24979746    
7.20000029   1.37891412    
7.30000019   1.49633956    
7.40000010   1.60037732    
7.50000000   1.68947268    
7.59999990   1.76223695    
7.70000029   1.81747139    
7.80000019   1.85418403    
7.90000010   1.87160957    
8.00000000   1.86922085    
8.10000038   1.84674001    
8.19999981   1.80414569    
8.30000019   1.74167395    
8.40000057   1.65982044    
8.50000000   1.55933595    
8.60000038   1.44121361    
8.69999981   1.30668485    
8.80000019   1.15719533    
8.90000057   0.994394958    
9.00000000   0.820112705    
9.10000038   0.636327863    
9.19999981   0.445154816    
9.30000019   0.248800844    
9.40000057   4.95488606E-02
9.50000000  -0.150278628    
9.60000038  -0.348357052    
9.69999981  -0.542378068    
9.80000019  -0.730095863    
9.90000057  -0.909344316    
10.0000000  -1.07807255

UMA procedureé um grupo de instruções que executam uma tarefa bem definida e podem ser chamadas de seu programa. Informações (ou dados) são passados ​​para o programa de chamada, para o procedimento como argumentos.

Existem dois tipos de procedimentos -

  • Functions
  • Subroutines

Função

Uma função é um procedimento que retorna uma única quantidade. Uma função não deve modificar seus argumentos.

A quantidade devolvida é conhecida como function valuee é denotado pelo nome da função.

Syntax

A sintaxe de uma função é a seguinte -

function name(arg1, arg2, ....)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

O exemplo a seguir demonstra uma função chamada area_of_circle. Ele calcula a área de um círculo com raio r.

program calling_func

   real :: a
   a = area_of_circle(2.0) 
   
   Print *, "The area of a circle with radius 2.0 is"
   Print *, a
   
end program calling_func


! this function computes the area of a circle with radius r  
function area_of_circle (r)  

! function result     
implicit none      

   ! dummy arguments        
   real :: area_of_circle   
   
   ! local variables 
   real :: r     
   real :: pi
   
   pi = 4 * atan (1.0)     
   area_of_circle = pi * r**2  
   
end function area_of_circle

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

The area of a circle with radius 2.0 is
   12.5663710

Observe que -

  • Você deve especificar implicit none tanto no programa principal quanto no procedimento.

  • O argumento r na função chamada é chamado dummy argument.

O resultado Opção

Se você quiser que o valor retornado seja armazenado em algum outro nome que não o nome da função, você pode usar o result opção.

Você pode especificar o nome da variável de retorno como -

function name(arg1, arg2, ....) result (return_var_name)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

Sub-rotina

Uma sub-rotina não retorna um valor, mas pode modificar seus argumentos.

Syntax

subroutine name(arg1, arg2, ....)    
   [declarations, including those for the arguments]    
   [executable statements]  
end subroutine [name]

Chamando uma subrotina

Você precisa invocar uma sub-rotina usando o call declaração.

O exemplo a seguir demonstra a definição e o uso de uma troca de sub-rotina, que altera os valores de seus argumentos.

program calling_func
implicit none

   real :: a, b
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
end program calling_func


subroutine swap(x, y) 
implicit none

   real :: x, y, temp   
   
   temp = x  
   x = y 
   y = temp  
   
end subroutine swap

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000

Especificando a intenção dos argumentos

O atributo intent permite que você especifique a intenção com a qual os argumentos são usados ​​no procedimento. A tabela a seguir fornece os valores do atributo intent -

Valor Usado como Explicação
dentro intenção (em) Usado como valores de entrada, não alterado na função
Fora intenção (fora) Usado como valor de saída, eles são substituídos
entrada intenção (inout) Os argumentos são usados ​​e substituídos

O exemplo a seguir demonstra o conceito -

program calling_func
implicit none

   real :: x, y, z, disc
   
   x = 1.0
   y = 5.0
   z = 2.0
   
   call intent_example(x, y, z, disc)
   
   Print *, "The value of the discriminant is"
   Print *, disc
   
end program calling_func


subroutine intent_example (a, b, c, d)     
implicit none     

   ! dummy arguments      
   real, intent (in) :: a     
   real, intent (in) :: b      
   real, intent (in) :: c    
   real, intent (out) :: d   
   
   d = b * b - 4.0 * a * c 
   
end subroutine intent_example

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

The value of the discriminant is
   17.0000000

Procedimentos Recursivos

A recursão ocorre quando uma linguagem de programação permite chamar uma função dentro da mesma função. É chamado de chamada recursiva da função.

Quando um procedimento chama a si mesmo, direta ou indiretamente, é chamado de procedimento recursivo. Você deve declarar este tipo de procedimento precedendo a palavrarecursive antes de sua declaração.

Quando uma função é usada recursivamente, o result opção deve ser usada.

A seguir está um exemplo, que calcula o fatorial para um determinado número usando um procedimento recursivo -

program calling_func
implicit none

   integer :: i, f
   i = 15
   
   Print *, "The value of factorial 15 is"
   f = myfactorial(15)
   Print *, f
   
end program calling_func

! computes the factorial of n (n!)      
recursive function myfactorial (n) result (fac)  
! function result     
implicit none     

   ! dummy arguments     
   integer :: fac     
   integer, intent (in) :: n     
   
   select case (n)         
      case (0:1)         
         fac = 1         
      case default    
         fac = n * myfactorial (n-1)  
   end select 
   
end function myfactorial

Procedimentos Internos

Quando um procedimento está contido em um programa, é chamado de procedimento interno do programa. A sintaxe para conter um procedimento interno é a seguinte -

program program_name     
   implicit none         
   ! type declaration statements         
   ! executable statements    
   . . .     
   contains         
   ! internal procedures      
   . . .  
end program program_name

O exemplo a seguir demonstra o conceito -

program mainprog  
implicit none 

   real :: a, b 
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
 
contains   
   subroutine swap(x, y)     
      real :: x, y, temp      
      temp = x 
      x = y  
      y = temp   
   end subroutine swap 
   
end program mainprog

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000

Um módulo é como um pacote onde você pode manter suas funções e sub-rotinas, caso esteja escrevendo um programa muito grande, ou suas funções ou sub-rotinas possam ser usadas em mais de um programa.

Módulos fornecem uma maneira de dividir seus programas entre vários arquivos.

Módulos são usados ​​para -

  • Empacotando subprogramas, dados e blocos de interface.

  • Definindo dados globais que podem ser usados ​​por mais de uma rotina.

  • Declarar variáveis ​​que podem ser disponibilizadas em qualquer rotina que você escolher.

  • Importar um módulo inteiramente, para uso, em outro programa ou sub-rotina.

Sintaxe de um Módulo

Um módulo consiste em duas partes -

  • uma parte de especificação para declaração de declarações
  • a contém parte para definições de sub-rotina e função

A forma geral de um módulo é -

module name     
   [statement declarations]  
   [contains [subroutine and function definitions] ] 
end module [name]

Usando um módulo em seu programa

Você pode incorporar um módulo em um programa ou sub-rotina pela instrução use -

use name

Observe que

  • Você pode adicionar quantos módulos forem necessários, cada um estará em arquivos separados e compilados separadamente.

  • Um módulo pode ser usado em vários programas diferentes.

  • Um módulo pode ser usado várias vezes no mesmo programa.

  • As variáveis ​​declaradas em uma parte da especificação do módulo são globais para o módulo.

  • As variáveis ​​declaradas em um módulo tornam-se variáveis ​​globais em qualquer programa ou rotina onde o módulo é usado.

  • A instrução de uso pode aparecer no programa principal, ou em qualquer outra sub-rotina ou módulo que utilize as rotinas ou variáveis ​​declaradas em um determinado módulo.

Exemplo

O exemplo a seguir demonstra o conceito -

module constants  
implicit none 

   real, parameter :: pi = 3.1415926536  
   real, parameter :: e = 2.7182818285 
   
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*,  "e = ", e     
   end subroutine show_consts 
   
end module constants 


program module_example     
use constants      
implicit none     

   real :: x, ePowerx, area, radius 
   x = 2.0
   radius = 7.0
   ePowerx = e ** x
   area = pi * radius**2     
   
   call show_consts() 
   
   print*, "e raised to the power of 2.0 = ", ePowerx
   print*, "Area of a circle with radius 7.0 = ", area  
   
end program module_example

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Pi = 3.14159274    
e =  2.71828175    
e raised to the power of 2.0 = 7.38905573    
Area of a circle with radius 7.0 = 153.938049

Acessibilidade de variáveis ​​e sub-rotinas em um módulo

Por padrão, todas as variáveis ​​e sub-rotinas em um módulo são disponibilizadas para o programa que está usando o código do módulo, pelo use declaração.

No entanto, você pode controlar a acessibilidade do código do módulo usando o private e publicatributos. Quando você declara alguma variável ou sub-rotina como privada, ela não está disponível fora do módulo.

Exemplo

O exemplo a seguir ilustra o conceito -

No exemplo anterior, tínhamos duas variáveis ​​de módulo, e e pi. Vamos torná-los privados e observar a saída -

module constants  
implicit none 

   real, parameter,private :: pi = 3.1415926536  
   real, parameter, private :: e = 2.7182818285 
   
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*, "e = ", e     
   end subroutine show_consts 
   
end module constants 


program module_example     
use constants      
implicit none     

   real :: x, ePowerx, area, radius 
   x = 2.0
   radius = 7.0
   ePowerx = e ** x
   area = pi * radius**2     
   
   call show_consts() 
   
   print*, "e raised to the power of 2.0 = ", ePowerx
   print*, "Area of a circle with radius 7.0 = ", area  
   
end program module_example

Quando você compila e executa o programa acima, ele exibe a seguinte mensagem de erro -

ePowerx = e ** x
   1
Error: Symbol 'e' at (1) has no IMPLICIT type
main.f95:19.13:

   area = pi * radius**2     
   1
Error: Symbol 'pi' at (1) has no IMPLICIT type

Desde a e e pi, ambos são declarados privados, o programa module_example não pode mais acessar essas variáveis.

No entanto, outras sub-rotinas do módulo podem acessá-los -

module constants  
implicit none 

   real, parameter,private :: pi = 3.1415926536  
   real, parameter, private :: e = 2.7182818285 
   
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*, "e = ", e     
   end subroutine show_consts 
   
   function ePowerx(x)result(ePx) 
   implicit none
      real::x
      real::ePx
      ePx = e ** x
   end function ePowerx
    
   function areaCircle(r)result(a)  
   implicit none
      real::r
      real::a
      a = pi * r**2  
   end function areaCircle
    
end module constants 


program module_example     
use constants      
implicit none     

   call show_consts() 
   
   Print*, "e raised to the power of 2.0 = ", ePowerx(2.0)
   print*, "Area of a circle with radius 7.0 = ", areaCircle(7.0)  
   
end program module_example

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

Pi = 3.14159274    
e = 2.71828175    
e raised to the power of 2.0 = 7.38905573    
Area of a circle with radius 7.0 = 153.938049

As funções intrínsecas são algumas funções comuns e importantes fornecidas como parte da linguagem Fortran. Já discutimos algumas dessas funções nos capítulos Arrays, Characters e String.

As funções intrínsecas podem ser categorizadas como -

  • Funções Numéricas
  • Funções Matemáticas
  • Funções de pesquisa numérica
  • Funções de manipulação de ponto flutuante
  • Funções de manipulação de bits
  • Funções de personagem
  • Funções de tipo
  • Funções Lógicas
  • Funções de matriz.

Discutimos as funções de array no capítulo Arrays. Na seção a seguir, fornecemos breves descrições de todas essas funções de outras categorias.

Na coluna do nome da função,

  • A representa qualquer tipo de variável numérica
  • R representa uma variável real ou inteira
  • X e Y representam variáveis ​​reais
  • Z representa variável complexa
  • W representa variável real ou complexa

Funções Numéricas

Sr. Não Descrição da função
1

ABS (A)

Ele retorna o valor absoluto de A

2

AIMAG (Z)

Ele retorna a parte imaginária de um número complexo Z

3

AINT (A [, KIND])

Ele trunca a parte fracionária de A em direção a zero, retornando um número real inteiro.

4

ANINT (A [, KIND])

Ele retorna um valor real, o número inteiro ou inteiro mais próximo.

5

CEILING (A [, KIND])

Ele retorna o menor número inteiro maior ou igual ao número A.

6

CMPLX (X [, Y, KIND])

Ele converte as variáveis ​​reais X e Y em um número complexo X + iY; se Y estiver ausente, 0 é usado.

7

CONJG (Z)

Ele retorna o conjugado complexo de qualquer número complexo Z.

8

DBLE (A)

Ele converte A em um número real de precisão dupla.

9

DIM (X, Y)

Ele retorna a diferença positiva de X e Y.

10

DPROD (X, Y)

Ele retorna o produto real de precisão dupla de X e Y.

11

FLOOR (A [, KIND])

Ele fornece o maior número inteiro menor ou igual ao número A.

12

INT (A [, KIND])

Ele converte um número (real ou inteiro) em inteiro, truncando a parte real para zero.

13

MAX (A1, A2 [, A3,...])

Ele retorna o valor máximo dos argumentos, todos sendo do mesmo tipo.

14

MIN (A1, A2 [, A3,...])

Ele retorna o valor mínimo dos argumentos, todos sendo do mesmo tipo.

15

MOD (A, P)

Ele retorna o resto de A na divisão por P, ambos os argumentos sendo do mesmo tipo (A-INT (A / P) * P)

16

MODULO (A, P)

Ele retorna A módulo P: (A-FLOOR (A / P) * P)

17

NINT (A [, KIND])

Ele retorna o número inteiro mais próximo do número A

18

REAL (A [, KIND])

Converte em tipo real

19

SIGN (A, B)

Ele retorna o valor absoluto de A multiplicado pelo sinal de P. Basicamente, ele transfere o sinal de B para A.

Exemplo

program numericFunctions
implicit none  

   ! define constants  
   ! define variables
   real :: a, b 
   complex :: z
   
   ! values for a, b 
   a = 15.2345
   b = -20.7689
    
   write(*,*) 'abs(a): ',abs(a),' abs(b): ',abs(b)   
   write(*,*) 'aint(a): ',aint(a),' aint(b): ',aint(b) 
   write(*,*) 'ceiling(a): ',ceiling(a),' ceiling(b): ',ceiling(b)   
   write(*,*) 'floor(a): ',floor(a),' floor(b): ',floor(b)  
    
   z = cmplx(a, b)
   write(*,*) 'z: ',z   
   
end program numericFunctions

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

abs(a): 15.2344999   abs(b): 20.7688999    
aint(a): 15.0000000  aint(b): -20.0000000    
ceiling(a): 16  ceiling(b): -20
floor(a): 15  floor(b): -21
z: (15.2344999, -20.7688999)

Funções Matemáticas

Sr. Não Descrição da função
1

ACOS (X)

Ele retorna o cosseno inverso no intervalo (0, π), em radianos.

2

ASIN (X)

Ele retorna o seno inverso no intervalo (-π / 2, π / 2), em radianos.

3

ATAN (X)

Ele retorna a tangente inversa no intervalo (-π / 2, π / 2), em radianos.

4

ATAN2 (Y, X)

Ele retorna a tangente inversa no intervalo (-π, π), em radianos.

5

COS (X)

Ele retorna o cosseno do argumento em radianos.

6

COSH (X)

Ele retorna o cosseno hiperbólico do argumento em radianos.

7

EXP (X)

Ele retorna o valor exponencial de X.

8

LOG (X)

Ele retorna o valor logarítmico natural de X.

9

LOG10 (X)

Ele retorna o valor logarítmico comum (base 10) de X.

10

SIN (X)

Ele retorna o seno de argumento em radianos.

11

SINH (X)

Ele retorna o seno hiperbólico do argumento em radianos.

12

SQRT (X)

Ele retorna a raiz quadrada de X.

13

TAN (X)

Ele retorna a tangente do argumento em radianos.

14

TANH (X)

Ele retorna a tangente hiperbólica do argumento em radianos.

Exemplo

O programa a seguir calcula a posição horizontal e vertical xey, respectivamente, de um projétil após um tempo, t -

Onde, x = ut cos a e y = ut sen a - g t2 / 2

program projectileMotion  
implicit none  

   ! define constants  
   real, parameter :: g = 9.8  
   real, parameter :: pi = 3.1415927  
   
   !define variables
   real :: a, t, u, x, y   
   
   !values for a, t, and u 
   a = 45.0
   t = 20.0
   u = 10.0
   
   ! convert angle to radians  
   a = a * pi / 180.0  
   x = u * cos(a) * t   
   y = u * sin(a) * t - 0.5 * g * t * t  
   
   write(*,*) 'x: ',x,'  y: ',y   
   
end program projectileMotion

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

x: 141.421356  y: -1818.57861

Funções de pesquisa numérica

Essas funções funcionam com um certo modelo de aritmética de inteiros e de ponto flutuante. As funções retornam propriedades de números do mesmo tipo da variável X, que podem ser reais e, em alguns casos, inteiros.

Sr. Não Descrição da função
1

DIGITS (X)

Ele retorna o número de dígitos significativos do modelo.

2

EPSILON (X)

Ele retorna o número que é quase insignificante em comparação com um. Em outras palavras, ele retorna o menor valor tal que REAL (1.0, KIND (X)) + EPSILON (X) não seja igual a REAL (1.0, KIND (X)).

3

HUGE (X)

Ele retorna o maior número do modelo

4

MAXEXPONENT (X)

Ele retorna o expoente máximo do modelo

5

MINEXPONENT (X)

Ele retorna o expoente mínimo do modelo

6

PRECISION (X)

Devolve a precisão decimal

7

RADIX (X)

Ele retorna a base do modelo

8

RANGE (X)

Ele retorna o intervalo do expoente decimal

9

TINY (X)

Ele retorna o menor número positivo do modelo

Funções de manipulação de ponto flutuante

Sr. Não Descrição da função
1

EXPONENT (X)

Ele retorna a parte expoente de um número de modelo

2

FRACTION (X)

Ele retorna a parte fracionária de um número

3

NEAREST (X, S)

Ele retorna o número de processador diferente mais próximo em determinada direção

4

RRSPACING (X)

Ele retorna o recíproco do espaçamento relativo dos números do modelo próximo ao número fornecido

5

SCALE (X, I)

Ele multiplica um real por sua base em uma potência inteira

6

SET_EXPONENT (X, I)

retorna a parte expoente de um número

7

SPACING (X)

Ele retorna o espaçamento absoluto dos números do modelo próximo ao número fornecido

Funções de manipulação de bits

Sr. Não Descrição da função
1

BIT_SIZE (I)

Ele retorna o número de bits do modelo

2

BTEST (I, POS)

Teste de bits

3

IAND (I, J)

E lógico

4

IBCLR (I, POS)

Bit claro

5

IBITS (I, POS, LEN)

Extração de bits

6

IBSET (I, POS)

Definir bit

7

IEOR (I, J)

Exclusivo ou

8

IOR (I, J)

Inclusive OU

9

ISHFT (I, SHIFT)

Mudança lógica

10

ISHFTC (I, SHIFT [, SIZE])

Mudança circular

11

NOT (I)

Complemento lógico

Funções de personagem

Sr. Não Descrição da função
1

ACHAR (I)

Ele retorna o Iº caractere na seqüência de intercalação ASCII.

2

ADJUSTL (STRING)

Ele ajusta a string deixada removendo quaisquer espaços em branco à esquerda e inserindo espaços em branco à direita

3

ADJUSTR (STRING)

Ele ajusta a string corretamente, removendo espaços em branco à direita e inserindo espaços em branco à esquerda.

4

CHAR (I [, KIND])

Ele retorna o Iº caractere na sequência de intercalação específica da máquina

5

IACHAR (C)

Ele retorna a posição do caractere na seqüência de intercalação ASCII.

6

ICHAR (C)

Ele retorna a posição do caractere na seqüência de intercalação específica da máquina (processador).

7

INDEX (STRING, SUBSTRING [, BACK])

Ele retorna a posição inicial mais à esquerda (mais à direita se BACK for .TRUE.) De SUBSTRING em STRING.

8

LEN (STRING)

Ele retorna o comprimento de uma string.

9

LEN_TRIM (STRING)

Ele retorna o comprimento de uma string sem caracteres em branco à direita.

10

LGE (STRING_A, STRING_B)

Lexicamente maior ou igual

11

LGT (STRING_A, STRING_B)

Lexicamente maior que

12

LLE (STRING_A, STRING_B)

Lexicamente menor ou igual

13

LLT (STRING_A, STRING_B)

Lexicamente menos que

14

REPEAT (STRING, NCOPIES)

Concatenação repetida

15

SCAN (STRING, SET [, BACK])

Ele retorna o índice do caractere mais à esquerda (mais à direita se BACK for .TRUE.) De STRING que pertence a SET, ou 0 se nenhum pertence.

16

TRIM (STRING)

Remove os caracteres em branco à direita

17

VERIFY (STRING, SET [, BACK])

Verifica o conjunto de caracteres em uma string

Funções de tipo

Sr. Não Descrição da função
1

KIND (X)

Ele retorna o valor do parâmetro do tipo de tipo.

2

SELECTED_INT_KIND (R)

Ele retorna uma espécie de parâmetro de tipo para o intervalo de expoente especificado.

3

SELECTED_REAL_KIND ([P, R])

Valor de parâmetro de tipo de tipo real, dada a precisão e intervalo

Função Lógica

Sr. Não Descrição da função
1

LOGICAL (L [, KIND])

Converta entre objetos de tipo lógico com diferentes parâmetros de tipo de tipo

Já discutimos que, nas versões mais antigas do Fortran, havia dois real tipos: o tipo real padrão e double precision tipo.

No entanto, o Fortran 90/95 fornece mais controle sobre a precisão dos tipos de dados reais e inteiros por meio do kind specifie.

O atributo de tipo

Diferentes tipos de números são armazenados de forma diferente dentro do computador. okindatributo permite que você especifique como um número é armazenado internamente. Por exemplo,

real, kind = 2 :: a, b, c
real, kind = 4 :: e, f, g
integer, kind = 2 :: i, j, k
integer, kind = 3 :: l, m, n

Na declaração acima, as variáveis ​​reais e, f e g têm mais precisão do que as variáveis ​​reais a, be c. As variáveis ​​inteiras l, m e n podem armazenar valores maiores e ter mais dígitos para armazenamento do que as variáveis ​​inteiras i, j e k. Embora isso seja dependente da máquina.

Exemplo

program kindSpecifier
implicit none

   real(kind = 4) :: a, b, c
   real(kind = 8) :: e, f, g
   integer(kind = 2) :: i, j, k
   integer(kind = 4) :: l, m, n
   integer :: kind_a, kind_i, kind_e, kind_l
   
   kind_a = kind(a)
   kind_i = kind(i)
   kind_e = kind(e)
   kind_l = kind(l)
   
   print *,'default kind for real is', kind_a
   print *,'default kind for int is', kind_i
   print *,'extended kind for real is', kind_e
   print *,'default kind for int is', kind_l
   
end program kindSpecifier

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

default kind for real is 4
default kind for int is 2
extended kind for real is 8
default kind for int is 4

Perguntando sobre o tamanho das variáveis

Existem várias funções intrínsecas que permitem interrogar o tamanho dos números.

Por exemplo, o bit_size(i)função intrínseca especifica o número de bits usados ​​para armazenamento. Para números reais, oprecision(x) função intrínseca, retorna o número de dígitos decimais de precisão, enquanto o range(x) função intrínseca retorna o intervalo decimal do expoente.

Exemplo

program getSize
implicit none

   real (kind = 4) :: a
   real (kind = 8) :: b
   integer (kind = 2) :: i
   integer (kind = 4) :: j

   print *,'precision of real(4) =', precision(a)
   print *,'precision of real(8) =', precision(b)
   
   print *,'range of real(4) =', range(a)
   print *,'range of real(8) =', range(b)
   

   print *,'maximum exponent of real(4) =' , maxexponent(a)
   print *,'maximum exponent of real(8) =' , maxexponent(b)
  
   print *,'minimum exponent of real(4) =' , minexponent(a)
   print *,'minimum exponent of real(8) =' , minexponent(b)
   
   print *,'bits in integer(2) =' , bit_size(i)
   print *,'bits in integer(4) =' , bit_size(j)
   
end program getSize

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

precision of real(4) = 6
precision of real(8) = 15
range of real(4) = 37
range of real(8) = 307
maximum exponent of real(4) = 128
maximum exponent of real(8) = 1024
minimum exponent of real(4) = -125
minimum exponent of real(8) = -1021
bits in integer(2) = 16
bits in integer(4) = 32

Obtendo o valor da espécie

Fortran fornece mais duas funções intrínsecas para obter o valor do tipo para a precisão necessária de inteiros e reais -

  • selected_int_kind (r)
  • selected_real_kind ([p, r])

A função selected_real_kind retorna um número inteiro que é o valor do parâmetro do tipo de tipo necessário para uma determinada precisão decimal p e intervalo de expoente decimal r. A precisão decimal é o número de dígitos significativos e o intervalo do expoente decimal especifica o menor e o maior número representável. O intervalo é, portanto, de 10-r a 10 + r.

Por exemplo, selected_real_kind (p = 10, r = 99) retorna o valor do tipo necessário para uma precisão de 10 casas decimais e um intervalo de pelo menos 10-99 a 10 + 99.

Exemplo

program getKind
implicit none

   integer:: i
   i = selected_real_kind (p = 10, r = 99) 
   print *,'selected_real_kind (p = 10, r = 99)', i
   
end program getKind

Quando você compila e executa o programa acima, ele produz o seguinte resultado -

selected_real_kind (p = 10, r = 99) 8

Existem várias ferramentas e bibliotecas Fortran. Alguns são gratuitos e outros são pagos.

A seguir estão algumas bibliotecas gratuitas -

  • RANDLIB, geradores de números aleatórios e distribuição estatística
  • BLAS
  • EISPACK
  • Guia GAMS – NIST para software de matemática disponível
  • Algumas estatísticas e outras rotinas do NIST
  • LAPACK
  • LINPACK
  • MINPACK
  • MUDPACK
  • Biblioteca Matemática NCAR
  • A coleção Netlib de softwares matemáticos, artigos e bancos de dados.
  • ODEPACK
  • ODERPACK, um conjunto de rotinas de classificação e ordenação.
  • Expokit para exponenciais de matriz de computação
  • SLATEC
  • SPECFUN
  • STARPAC
  • Biblioteca estatística StatLib
  • TOMS
  • Classificando e mesclando strings

As seguintes bibliotecas não são gratuitas -

  • A biblioteca numérica NAG Fortran
  • A biblioteca IMSL Visual Numerics
  • Receitas Numéricas

O estilo de programação consiste em seguir algumas regras durante o desenvolvimento de programas. Essas boas práticas transmitem valores como legibilidade e clareza ao seu programa.

Um bom programa deve ter as seguintes características -

  • Readability
  • Estrutura lógica adequada
  • Notas e comentários autoexplicativos

Por exemplo, se você fizer um comentário como o seguinte, não será de muita ajuda -

! loop from 1 to 10 
do i = 1,10

No entanto, se você está calculando o coeficiente binomial e precisa desse loop para nCr, um comentário como este será útil -

! loop to calculate nCr 
do i = 1,10
  • Blocos de código recuados para tornar vários níveis de código claros.

  • Códigos de autoverificação para garantir que não haverá erros numéricos como divisão por zero, raiz quadrada de um número real negativo ou logaritmo de um número real negativo.

  • Incluir códigos que garantem que as variáveis ​​não tenham valores ilegais ou fora do intervalo, ou seja, validação de entrada.

  • Não colocar cheques onde seria desnecessário e retarda a execução. Por exemplo -

real :: x 
x = sin(y) + 1.0

if (x >= 0.0) then
   z = sqrt(x)
end if
  • Código claramente escrito usando algoritmos apropriados.
  • Dividindo as expressões longas usando o marcador de continuação '&'.
  • Criação de nomes de variáveis ​​significativos.

Uma ferramenta de depuração é usada para pesquisar erros nos programas.

Um programa depurador percorre o código e permite que você examine os valores nas variáveis ​​e outros objetos de dados durante a execução do programa.

Ele carrega o código-fonte e você deve executar o programa dentro do depurador. Os depuradores depuram um programa por -

  • Definindo pontos de interrupção,
  • Percorrendo o código-fonte,
  • Definindo pontos de observação.

Os pontos de interrupção especificam onde o programa deve parar, especificamente após uma linha crítica de código. Execuções do programa após as variáveis ​​serem verificadas em um ponto de interrupção.

Os programas depuradores também verificam o código-fonte linha por linha.

Os pontos de observação são os pontos onde os valores de algumas variáveis ​​precisam ser verificados, especialmente após uma operação de leitura ou gravação.

O depurador gdb

O depurador gdb, o depurador GNU vem com o sistema operacional Linux. Para o sistema X windows, gdb vem com uma interface gráfica e o programa é denominado xxgdb.

A tabela a seguir fornece alguns comandos em gdb -

Comando Objetivo
pausa Definindo um ponto de interrupção
corre Inicia a execução
cont Continua a execução
Próximo Executa apenas a próxima linha do código-fonte, sem entrar em qualquer chamada de função
degrau Execute a próxima linha do código-fonte entrando em uma função no caso de uma chamada de função.

O depurador dbx

Existe outro depurador, o depurador dbx, para Linux.

A tabela a seguir fornece alguns comandos em dbx -

Comando Objetivo
parar [var] Define um ponto de interrupção quando o valor da variável var muda.
parar em [proc] Ele para a execução quando um procedimento proc é inserido
pare em [linha] Ele define um ponto de interrupção em uma linha especificada.
corre Inicia a execução.
cont Continua a execução.
Próximo Executa apenas a próxima linha do código-fonte, sem entrar em nenhuma chamada de função.
degrau Execute a próxima linha do código-fonte entrando em uma função no caso de uma chamada de função.