Lunghi interni a Fortran
-
13-09-2020 - |
Domanda
Sto cercando di lavorare con numeri di grandi dimensioni (~ 10 ^ 14), e ho bisogno di poterli memorizzarli e iterare su loop di quella lunghezza, I.e.
n=SOME_BIG_NUMBER
do i=n,1,-1
.
Ho provato la solita notazione stellare, kind=8
ecc. Ma nulla sembra funzionare.
Quindi ho controllato la funzione intrinseca huge
e il codice:
program inttest
print *,huge(1)
print *,huge(2)
print *,huge(4)
print *,huge(8)
print *,huge(16)
print *,huge(32)
end program inttest
.
Produce il numero 2147483647 in tutti i casi.Perchè è questo?Sto usando Gfortran (F95) su una macchina a 64 bit.
Se avrò bisogno di una biblioteca Bignum, quale si suggeriscono la gente?
Soluzione
Le versioni Gfortran che utilizzo, 4.3, 4.4 e 4.5 su un Mac, supportano numeri interi a 8 byte. Il modo migliore per selezionare un tipo variabile in Fortran>= 90 è utilizzare una funzione intrinseca per specificare la precisione di cui hai bisogno. Prova:
integer, parameter :: LargeInt_K = selected_int_kind (18)
integer (kind=LargeInt_K) :: i, n
.
Per ottenere almeno 18 cifre decimali, che in genere saranno un numero intero di 8 byte.
con Gfortran 4.3, enormi output (1_largeint_k) 9223372036854775807. Quando hai scritto enorme (1), ecc., Per impostazione predefinita, la costante è stata un numero intero predefinito, qui evidentemente 4 byte dal restituito enorme 2147483647. Quindi a volte è necessario specificare così La precisione delle costanti, non solo le variabili - più comunemente questo viaggi in cui perdono figure significative su una vera costante, che è predefinita a singola precisione.
Vedi anche Fortran: Integer * 4 vs intero (4) vs intero (tipo= 4)
Di solito Gfortran ha il nome del comando Gfortran. Potrebbe f95 essere un compilatore diverso? Prova "Gfortran -v" e "F95 -v".
Altri suggerimenti
Hai frainteso la definizione precisa della funzione HUGE
.HUGE(num)
restituisce il numero più grande con lo stesso tipo e tipo come num
.Il valore restituito ha anche lo stesso tipo e tipo come num
.Poiché tutti i tuoi valori di input sono (predefiniti) numeri interi generacodicitagCode, correttamente, restituisce il più grande numero intero predefinito.
HUGE
non restituisce il numero intero più grande con HUGE(num)
.Né kind=num
restituisce il numero più grande rappresentabile nei byte HUGE(num)
.Mentre molti compilatori usano num
e integer(kind=4)
etc per numeri interi di 4 e 8 byte, questo non è garantito dallo standard linguistico e non può essere invocato per essere portatile.
@ La risposta di MSB ti dice come fare ciò che vuoi, sto solo seguendo con alcuni chiarimenti.
Sommario: considerare la ricerca delle opzioni del compilatore.
È stato un tempo L-O-N-G da quando ho fatto Fortran, e non ricordo di usare enorme (), ma ho guardato un po '. La mia macchina Intel Linux ha Gfortran 4.1.2. Ho trovato che dovevo compilare con l'opzione -Fdefault-integer-8 acceso per farlo funzionare per numeri interi a 64 bit. In particolare, con questo codice:
program inttest
print *, huge(1)
end program inttest
.
Esecuzione
.$ Gfortran INTTEST.Per
ha creato un eseguibile che stampato:
.2147483647
Tuttavia, in esecuzione:
.$ GFORTRAN -FDEFAULT-INTEGER-8 INTTEST.PER
ha comportato un eseguibile che ha dato l'uscita:
.9223372036854775807
Inoltre, quando ho dichiarato una variabile come numero intero * 8 e compilato senza l'opzione -fdefault-integer-8, ho ricevuto un errore. Il codice:
program inttest2
integer*8 test_int
test_int = 9223372036854775807
print *, test_int
end program inttest2
.
Esecuzione
.$ Gfortran INTTEST2.Per
ha comportato
.In file INTTEST.Per: 4
.test_int = 9223372036854775807 1
Errore: intero troppo grande per il suo tipo a (1)
Tuttavia, le cose funzionavano bene quando ho compilato con l'opzione -fdefault-integer-8 e ho ottenuto un eseguibile che stampato
.9223372036854775807
Forse ci sono altre opzioni Gfortran che sarebbero utili, ma non ho indagato ulteriormente.
Concesso, questo non ti prende 10 ^ 14, ma può aiutare a spiegare i risultati che hai visto.