2012-03-05 21 views
10

Fortran è completamente nuovo per me, qualcuno può aiutarmi a risolvere il problema follwing? Voglio scoprire tutti i numeri di numeri interi e il valore più grande e più piccolo per ogni tipo di numero sul mio pc. Ho il codice elencato di seguito:Fortran: il più grande e il più piccolo intero

program intkind 
implicit none 

integer :: n=1 
integer :: integer_range =1 


do while(integer_range /= -1) 
    print*, "kind_number ", selected_int_kind(n) 
    call rang(integer_range) 
    n = n *2 
    integer_range = selected_int_kind(n) 
end do 

contains 
subroutine rang(largest) 
    integer largest 
    print*, huge(largest) 

end subroutine 

end 

Il numero intero di numeri che ottengo sono: 1,2,4,8.

  1. Perché ogni grande intero per ogni numero di specie lo stesso: 2147483647? E c'è una funzione intrinseca per il più piccolo intero?

  2. Come posso mantenere il numero di tipo intero quando viene chiamato il sottoprogramma rang? Penso che sia la chiave per il più grande intero.

+0

Solo per qualcuno che viene su questo molto più tardi. Sebbene non ci sia intrinseco, puoi sempre usare '-huge (n)' per calcolare il più piccolo numero intero disponibile. – NoseKnowsAll

risposta

15

la subroutine:

subroutine rang(largest) 
    integer :: largest 
    print *, huge(largest) 
end subroutine 

prende come input un intero predefinito di dimensioni, e stampa il valore più grande possibile che si inserisce in quel intero predefinito di dimensioni. Sarà sempre return enorme (intero predefinito) che è, nella maggior parte dei sistemi, enorme (numero intero a 4 byte) o 2147483647. huge considera solo il tipo di variabile; non è interpretare la variabile in alcun modo. L'unico modo per fare ciò che si sta tentando di fare sopra è con i tipi derivati ​​parametrizzati, che sono abbastanza nuovi che il supporto per i compilatori è ancora un po 'macchiato.

Se si vuole dare un'occhiata a intervalli di diversi tipi di numeri interi, si dovrà utilizzare diverse variabili:

program integerkinds 
    use iso_fortran_env 
    implicit none 

    integer :: i 
    integer(kind=int8) :: i8 
    integer(kind=int16) :: i16 
    integer(kind=int32) :: i32 
    integer(kind=int64) :: i64 

    integer(kind=selected_int_kind(6)) :: j6 
    integer(kind=selected_int_kind(15)):: j15 

    print *,'Default:' 
    print *, huge(i) 
    print *,'Int8:' 
    print *, huge(i8) 
    print *,'Int16:' 
    print *, huge(i16) 
    print *,'Int32:' 
    print *, huge(i32) 
    print *,'Int64:' 
    print *, huge(i64) 

    print *,'' 

    print *,'Selected Integer Kind 6:' 
    print *, huge(j6) 

    print *,'Selected Integer Kind 15:' 
    print *, huge(j15) 

end program integerkinds 

Esecuzione dà:

$ ./intkinds 
Default: 
    2147483647 
Int8: 
    127 
Int16: 
    32767 
Int32: 
    2147483647 
Int64: 
    9223372036854775807 

Selected Integer Kind 6: 
    2147483647 
Selected Integer Kind 15: 
    9223372036854775807 
+0

IF: selected_int_kind (9) = 4, intero (tipo = selected_int_kind (9)) :: j4 ed enorme (j4) è: 2147483647 sul mio pc. la definizione di selected_int_kind (r) dice che può rappresentare tutti i valori interi n nell'intervallo -10 ** r < n > 10 ** r. Se r = 9, allora il valore più grande è 10 ** 9-1, è inferiore a 2147483647 (enorme (j4)), perché? Non posso anderstandlo. – echo

+0

Prima parte: sì, enorme (j4) dovrebbe essere 2147483647, perché j4 è definito come intero (kind = selected_int_kind (9)). Ma nota che dovevi * define * j4 per essere di quel tipo. Non puoi semplicemente cambiare i tipi dopo che le variabili sono state definite; ad esempio, puoi chiamare selected_int_kind() tutte le volte che vuoi dopo e non cambia nulla. L'esempio sopra mostra come definire i tipi dei vari tipi. –

-6

puramente come un addendum, o prospettiva alternativa, le variabili Fortran sono definite in termini di numero di byte di memoria allocati alla var. In effetti, tutti i compilatori comparabili definiscono le vars in termini di byte allocati, altrimenti sarebbe molto difficile per il sistema allocare/archiviare in memoria, e molto molto difficile eseguire aritmetiche ecc. Senza tali.

Per alcuni, come me, è più facile vedere cosa sta accadendo usando una notazione leggermente più vecchia (piuttosto che il "tipo konfusion".) In particolare, molti compilatori forniscono una corrispondenza diretta 1: 1 tra Tipo e bytes/var, che rende il calcolo del più grande/più piccolo intero abbastanza semplice (alcuni compilatori usano una corrispondenza non lineare o non diretta) .Anche se si è sicuri di prendere nota dell'assistenza alla portabilità alla fine.Ad esempio

Integer(1)  :: Int1  ! corresponds to a 1 byte integer 
Integer(2)  :: Int1  ! corresponds to a 2 byte integer 
Integer(4)  :: Int1  ! corresponds to a 4 byte integer 
Integer(8)  :: Int1  ! corresponds to an 8 byte integer 
Integer(1)  :: Int1  ! corresponds to a 1 byte integer 
Integer(2)  :: Int1  ! corresponds to a 2 byte integer 
Integer(4)  :: Int1  ! corresponds to a 4 byte integer 
Integer(8)  :: Int1  ! corresponds to an 8 byte integer 

La notazione simile si applica ad altri tipi di Fortran (Real, Logical, ecc.) Tutti i tipi var hanno un numero predefinito di byte assegnati se la "dimensione" non è specificata.

Il numero massimo di byte per un particolare tipo dipende anche dal compilatore e dal sistema (ad es. Integer (16) non è disponibile su tutti i sistemi, ecc.).

Un byte è 8 bit, quindi un singolo byte dovrebbe essere in grado di contenere il valore più grande di 2^8 = 256 se numerazione da 1 o = 255, a partire da 0.

Tuttavia, in Fortran, (quasi tutti) i varici numerici sono "firmati". Ciò significa che da qualche parte nella rappresentazione bit è necessario un bit per tracciare se il numero è un numero + ve o un numero -ve. Quindi in questo esempio, il massimo sarebbe 2^7, poiché un bit è "perso/riservato" per le informazioni sul "segno". Pertanto, i valori possibili per un intero con segno a 1 byte sono -127: +128 (notare la somma Abs (limiti) a 255, poiché "0" occupa un posto, per un totale di 256 "cose", come dovrebbe essere).

Una regola simile si applica a tutti questi vars, con semplicemente l'esponente "n", in 2^n, che varia in base al numero di byte. Ad esempio, una variabile Integer (8) ha 8 byte o 64 bit, con 1 bit perso/riservato per le informazioni sul segno, quindi il valore massimo possibile sarebbe 2^63 = 9223372036854775808, se numerazione da 1 o = 4611686018427387904 all'avvio da 0.

il modello di dati standard Integer sarebbe essere generalizzato come:

IntNum = s * Sum[ w(k) * 2^(k-1), k=1:(NumBytes*8)-1], 

dove s = "segno" (+/- 1), w (k) è 1 o 0 per il bit KTH valore.

Non è necessario utilizzare numeri espliciti o vv en nelle dichiarazioni di tipo; Le costanti di tempo di compilazione definite dall'utente (cioè i parametri) sono consentite. Ad esempio

Integer, Parameter  :: DP = Kind(1.0d0) ! a standard Double Precision/8-byte declaration 
Integer, Parameter  :: I4B = 4    ! NOTICE, here the "Integer" bit has not been explicitly "sized", so defaults to "Integer(4)" 
! 
Real(DP)     :: ADoublePrecReal  ! an 8-byte Real (approx 15 decimal places with exp +/- approx 300, see Real data model) 
! 
Integer(I4B)    :: AStandardInt  ! a 4-byte integer. 

Poiché l'istruzione parametro può essere in un altro modulo accessibile tramite Uso ecc, è una questione semplice ricompilazione grande complesso codice per le definizioni alternative di "precisione" desiderato. Ad esempio, se DP è modificato in Tipo (1.0), allora ovunque quella dichiarazione viene applicata diventerà reale "precisione singola".

Le funzioni intrinseche di Fortran Huge(), Tiny() ecc. Aiutano a determinare cosa è possibile su un dato sistema.

Molto altro può essere realizzato con i "bit" intrinseci di Fortran e altri strumenti/metodi.

+6

Questa risposta inizia errata: le variabili Fortran non sono definite in termini di numero di byte occupati. I selettori di tipo, gli interi in un'espressione come 'integer (8)' o 'real (4)', identificano semplicemente uno dei tipi supportati dal compilatore. Il compilatore NAG Fortran, ad esempio, imposta come valore predefinito 'integer (2) 'per interi a 4 byte e' intero (3) 'per interi a 8 byte. È comune per i compilatori utilizzare selettori di tipo che corrispondono al numero di byte utilizzati, ma non è richiesto dallo standard. –

+3

Questo è un malinteso comune. Vedi anche http://stackoverflow.com/questions/3170239/fortran-integer4-vs-integer4-vs-integerkind-4 –

+0

Sì, ogni venditore di compilatori può fare ciò che vuole e spesso lo fa. E sì, avrebbe aiutato ad avere più di un enfasi sulla varianza tra i sistemi (a quanto pare, una volta non è abbastanza per alcuni). Tuttavia, i commenti originali sono corretti per compilatori di Compaq, DEC, IBM, CRAY, Oracle, Intel, ecc. Ecc., Con i tipi/byte corrispondenti esattamente come sono.Ho anche enfatizzato l'uso di Parameters for Kind globali come buone pratiche per gli stessi motivi che altri citano solo dopo i reparti. Inoltre, è abbastanza certo che la formulazione del modello Integer Data sia corretta, controlla qualsiasi libro .. – DrOli