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 | só | 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 A 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 A 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. |