Entradas largas en Fortran
-
13-09-2020 - |
Pregunta
Estoy tratando de trabajar con números grandes (~10^14), y necesito poder almacenarlos e iterar sobre bucles de esa longitud, es decir,
n=SOME_BIG_NUMBER
do i=n,1,-1
Probé la notación de estrellas habitual, kind=8
etc.Pero nada parece funcionar.Luego revisé el huge
función intrínseca, y el 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
produce el número 2147483647 en todos los casos.¿Por qué es esto?Estoy usando gfortran (f95) en una máquina de 64 bits.
Si voy a necesitar una biblioteca bignum, ¿cuál sugiere la gente?
Solución
Las versiones de GFORRAN que yo uso, 4.3, 4.4 y 4.5 en una MAC, soportan enteros de 8 bytes. La mejor manera de seleccionar un tipo variable en FORTRAN>= 90 es usar una función intrínseca para especificar la precisión que necesita. Prueba:
integer, parameter :: LargeInt_K = selected_int_kind (18)
integer (kind=LargeInt_K) :: i, n
para obtener al menos 18 dígitos decimales, que normalmente serán un entero de 8 bytes.
con GFORRAN 4.3, enormes (1_largeint_k) Salidas 9223372036854775807. Cuando escribió enorme (1), etc., por defecto, la constante fue un entero predeterminado, aquí evidentemente 4 bytes desde que se devolvió 2147483647., por lo que a veces necesitas especificar La precisión de las constantes, no solo las variables, más comúnmente, los viajes a las personas se levantan cuando pierden figuras significativas en una constante real, lo que por defecto es una precisión única.
También vea FORTRAN: INTEGER * 4 VS INTEGER (4) VS entero (tipo= tipo= 4)
Por lo general, GFORTRAN tiene el nombre del comando GFORTRAN. ¿Podría F95 ser un compilador diferente? Pruebe "GFORRAN -V" y "F95 -V".
Otros consejos
Has entendido mal la definición precisa de HUGE
función. HUGE(num)
devuelve el número más grande con el mismo tipo y tipo que num
.El valor devuelto también tiene el mismo tipo y tipo que num
.Dado que todos sus valores de entrada son enteros (predeterminados) HUGE
, correctamente, devuelve el mayor número entero de tamaño predeterminado.
HUGE(num)
no devuelve el entero más grande con kind=num
.Ni tampoco HUGE(num)
devolver el mayor número representable en num
bytes.Si bien muchos compiladores usan integer(kind=4)
y integer(kind=8)
etc. para enteros de 4 y 8 bytes, esto no está garantizado por el estándar del lenguaje y no se puede confiar en que sea portátil.
La respuesta de @MSB te dice cómo hacer lo que quieres, solo estoy interviniendo con algunas aclaraciones.
Resumen: Considere mirar las opciones del compilador.
Ha sido un tiempo L-O-N-G desde que he hecho Fortran, y no recuerdo que estoy usando enorme (), pero miré esto un poco. Mi máquina Intel Linux tiene GFORTRAN 4.1.2. Descubrí que tenía que compilar con la opción -fdefault-enter-8 encendida para que funcione para los enteros de 64 bits. Específicamente, con este código:
program inttest
print *, huge(1)
end program inttest
corriendo
$ GFORRAN INTTEST.FOR
Creado un ejecutable que imprimió:
2147483647
Sin embargo, ejecutando:
$ GFORTRAN -FDEFAULT-INTEGER-8 INTTEST.FOR
dio lugar a un ejecutable que dio la salida:
9223372036854775807
Además, cuando declaré una variable como entero * 8 y compilada sin la opción -fdefault-enteger-8, obtuve un error. El código:
program inttest2
integer*8 test_int
test_int = 9223372036854775807
print *, test_int
end program inttest2
corriendo
$ GFORRAN INTTEST2.Por
resultó en
en el archivo inttest.for: 4
test_int = 9223372036854775807 1
Error: entero demasiado grande para su tipo en (1)
Sin embargo, las cosas funcionaban bien cuando compilié con la opción -fdefault-integer-8 y obtuve un ejecutable que imprimió
9223372036854775807
Tal vez haya otras opciones de Gforterán que serían útiles, pero no investigamos más adelante.
concedida, esto todavía no lo consigue 10 ^ 14, pero puede ayudar a explicar los resultados que vio.