Ints longos em Fortran
-
13-09-2020 - |
Pergunta
Estou tentando trabalhar com números grandes (~ 10 ^ 14) e preciso armazená-los e iterar em loops desse comprimento, ou seja,
n=SOME_BIG_NUMBER
do i=n,1,-1
Eu tentei a notação de estrela usual, kind=8
etc.Mas nada parece funcionar.Então eu verifiquei o huge
função intrínseca e o código:
program inttest
print *,huge(1)
print *,huge(2)
print *,huge(4)
print *,huge(8)
print *,huge(16)
print *,huge(32)
end program inttest
produz o número 2147483647 em todos os casos.Por que é isso?Estou usando o gfortran (f95) em uma máquina de 64 bits.
Se vou precisar de uma biblioteca bignum, qual delas as pessoas sugerem?
Solução
As versões do gfortran que uso, 4.3, 4.4 e 4.5 em um Mac, suportam números inteiros de 8 bytes.A melhor maneira de selecionar um tipo de variável em Fortran >= 90 é usar uma função intrínseca para especificar a precisão necessária.Tentar:
integer, parameter :: LargeInt_K = selected_int_kind (18)
integer (kind=LargeInt_K) :: i, n
para obter pelo menos 18 dígitos decimais, que normalmente serão um número inteiro de 8 bytes.
Com o gfortran 4.3, enormes (1_LargeInt_K) geram 9223372036854775807.Quando você escreveu enorme (1), etc., por padrão a constante era um número inteiro padrão, aqui evidentemente 4 bytes, já que enorme retornou 2147483647.Então, às vezes, você precisa especificar a precisão de constantes, não apenas de variáveis - mais comumente, isso confunde as pessoas quando elas perdem algarismos significativos em uma constante real, cujo padrão é precisão única.
Veja também Fortran:inteiro*4 vs inteiro(4) vs inteiro(tipo=4)
Normalmente gfortran tem o nome de comando gfortran.O f95 poderia ser um compilador diferente?Experimente "gfortran -v" e "f95 -v".
Outras dicas
Você entendeu mal a definição precisa do HUGE
função. HUGE(num)
retorna o maior número com o mesmo tipo e tipo que num
.O valor retornado também tem o mesmo tipo e tipo que num
.Como todos os seus valores de entrada são números inteiros (padrão) HUGE
, corretamente, retorna o maior número inteiro de tamanho padrão.
HUGE(num)
não retorna o maior número inteiro com kind=num
.Nem faz HUGE(num)
retornar o maior número representável em num
bytes.Embora muitos compiladores usem integer(kind=4)
e integer(kind=8)
etc. para números inteiros de 4 e 8 bytes, isso não é garantido pelo padrão de linguagem e não pode ser considerado portátil.
A resposta do @MSB diz como fazer o que você deseja, estou apenas introduzindo alguns esclarecimentos.
Resumo:Considere examinar as opções do compilador.
Já faz muito tempo que não faço FORTRAN e não me lembro de usar HUGE (), mas olhei um pouco para isso.Minha máquina Intel Linux possui gfortran 4.1.2.Descobri que precisava compilar com a opção -fdefault-integer-8 ativada para fazê-la funcionar com números inteiros de 64 bits.Especificamente, com este código:
program inttest
print *, huge(1)
end program inttest
correndo
$ gfortran inttest.for
criou um executável que imprimiu:
2147483647
No entanto, executando:
$ gfortran -fdefault-integer-8 inttest.for
resultou em um executável que deu a saída:
9223372036854775807
Além disso, quando declarei uma variável como inteiro*8 e compilei sem a opção -fdefault-integer-8, recebi um erro.O código:
program inttest2
integer*8 test_int
test_int = 9223372036854775807
print *, test_int
end program inttest2
correndo
$ gfortran inttest2.for
resultou em
No arquivo inttest.for:4
test_int = 9223372036854775807 1
Erro:Número inteiro muito grande para seu tipo em (1)
No entanto, as coisas funcionaram bem quando compilei com a opção -fdefault-integer-8 e obtive um executável que imprimiu
9223372036854775807
Talvez existam outras opções de gfortran que seriam úteis, mas não investiguei mais.
É verdade que isso ainda não dá 10 ^ 14, mas pode ajudar a explicar os resultados que você viu.