2012-03-05 51 views
10

Fortran es completamente nuevo para mí, ¿alguien me puede ayudar a resolver el problema? Quiero averiguar todos los números enteros y el valor más grande y el más pequeño para cada número de clase en mi pc. Tengo código enumerado a continuación:Fortran: el número entero más grande y el más pequeño

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 

Los números enteros que obtengo son: 1,2,4,8.

  1. ¿Por qué es cada mayor entero para cada número de la misma especie: 2147483647? ¿Y hay una función intrínseca para el entero más pequeño?

  2. ¿Cómo puedo mantener el número entero de tipo cuando se llama a la subrutina rang? Creo que es la clave del número entero más grande.

+0

Solo para alguien que se presente mucho más tarde. Si bien no es intrínseco, siempre puede usar '-huge (n)' para calcular el entero más pequeño disponible. – NoseKnowsAll

Respuesta

15

Su subrutina:

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

toma como entrada un número entero de tamaño predeterminado, e imprime el valor más grande posible que quepa en ese entero de tamaño predeterminado. Será siempre return enorme (entero por defecto) que es, en la mayoría de los sistemas, enorme (4 bytes de entero) o 2147483647. huge considera solo el tipo de variable; no interpretar la variable de ninguna manera. La única manera en que puede hacer lo que intenta hacer arriba es con los tipos derivados parametrizados, que son lo suficientemente nuevos como para admitirlos en los compiladores.

Si quieres echar un vistazo a los rangos de diferentes tipos de números enteros, que tendrá que utilizar diferentes variables:

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 

funcionar, se:

$ ./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, entero (kind = selected_int_kind (9)) :: j4 y huge (j4) es: 2147483647 en mi pc. la definición de selected_int_kind (r) dice que puede representar todos los valores enteros n en el rango -10 ** r < n > 10 ** r. SI r = 9, entonces el valor más grande es 10 ** 9-1, es menor que 2147483647 (enorme (j4)), ¿por qué? No puedo entenderlo. – echo

+0

Primera parte: sí, enorme (j4) debería ser 2147483647, porque j4 se define como entero (kind = selected_int_kind (9)). Pero ten en cuenta que debes * definir * j4 para que sea de ese tipo. No puede simplemente cambiar tipos después de que se hayan definido las variables; por ejemplo, puedes llamar a selected_int_kind() tantas veces como quieras luego y no cambia nada. El ejemplo anterior muestra cómo definir tipos de varios tipos. –

-6

Puramente como adición, o perspectiva alternativa, las variables de Fortran se definen en términos del número de bytes de memoria asignados a la var. De hecho, todos los compiladores comparables definen vars en términos de bytes asignados, de lo contrario sería muy difícil para el sistema asignar/almacenar en la memoria, y muy difícil de realizar aritmética, etc. sin ellos.

Para algunos, como yo, es más fácil ver lo que está pasando utilizando una notación un poco más antigua (en lugar de la "clase konfusion" .En particular, muchos compiladores proporcionan una correspondencia directa 1: 1 entre Tipo y bytes/var, que luego hace que el cálculo del entero más grande/pequeño sea bastante sencillo (algunos compilan utilizando una correspondencia no lineal o no directa). Aunque asegúrese de tomar nota de la asistencia de portabilidad al final. Por ejemplo

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 notación similar se aplica a otros tipos Fortran (Real, Lógica, etc.). Todos los tipos var tienen un número predeterminado de bytes asignados si no se especifica el "tamaño".

El número máximo de bytes para un tipo particular también depende del compilador y del sistema (p. Entero (16) no está disponible en todos los sistemas, etc.).

Un byte es de 8 bits, por lo que un solo byte debería ser capaz de acomodar el mayor valor de 2^8 = 256 si la numeración es de 1, o = 255, cuando se comienza desde 0.

Sin embargo, en Fortran, (casi todos) los vars numéricos están "firmados". Eso significa que en algún lugar de la representación de bit se requiere un bit para rastrear si el número es un número + ve o un número -ve. Entonces, en este ejemplo, el máximo sería 2^7, ya que un bit está "perdido/reservado" para la información del "signo". Por lo tanto, los valores posibles para un entero de 1 byte son -127: +128 (observe que la suma de Abs (límites) es 255, ya que "0" ocupa un lugar, para un total de 256 "cosas", como debería ser ser).

Se aplica una regla similar para todos estos valores variables, con simplemente el exponente "n", en 2^n, que varía en función del número de bytes. Por ejemplo, un entero (8) var tiene 8 bytes, o 64 bits, con 1 bit perdido/reservado para la información del signo, por lo que el mayor valor posible sería 2^63 = 9223372036854775808, si es de 1, o = 4611686018427387904 al comenzar desde 0.

se generaliza el modelo de datos estándar entero como:

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

donde s = "señal" (+/- 1), w (k) es 1 o 0 para el bit k-ésimo valor.

No es necesario utilizar números explícitos o env vars en las declaraciones de tipo; las constantes de tiempo de compilación definidas por el usuario (es decir, los parámetros) están permitidas. Por ejemplo

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. 

Desde la declaración de parámetros puede estar en otro módulo accesible a través de uso, etc, es una simple cuestión de volver a compilar código gran complejo para las definiciones alternativas de "precisión" deseada. Por ejemplo, si DP se edita según Kind (1.0), en todas partes en que se aplique esa declaración se convertirá en "precisión única" Real.

Las funciones intrínsecas de Fortran Enorme(), Tiny() etc. ayudan a determinar qué es posible en un sistema dado.

Mucho más se puede lograr con Fortran "bit" intrínsecos y otras herramientas/métodos.

+6

Esta respuesta comienza mal: Fortran variables no se definen en términos de la cantidad de bytes que ocupan. Los selectores tipo, los enteros en una expresión como 'entero (8)' o 'real (4)', simplemente identifican uno de los tipos admitidos por el compilador. El compilador Fortran de NAG, por ejemplo, se predetermina a 'entero (2)' para enteros de 4 bytes y 'entero (3)' para enteros de 8 bytes. Es común que los compiladores usen selectores de tipo que coincidan con la cantidad de bytes utilizados, pero el estándar no los exige. –

+3

Este es un error común. Consulte también http://stackoverflow.com/questions/3170239/fortran-integer4-vs-integer4-vs-integerkind-4 –

+0

Sí, cada proveedor de compiladores puede hacer lo que quiera, y a menudo lo hace. Y sí, hubiera ayudado tener más de un énfasis en la varianza entre sistemas (aparentemente, una vez no es suficiente para algunos). Aún así, los comentarios originales realizados son correctos para los compiladores de Compaq, DEC, IBM, CRAY, Oracle, Intel, etc., con los tipos/bytes que corresponden exactamente como están.También he enfatizado el uso de los Parámetros globales como buenas prácticas por las mismas razones que otros solo citan después. Además, es bastante cierto que la formulación del modelo de datos enteros es correcta, verifique cualquier libro. – DrOli

Cuestiones relacionadas