Fortran: наибольшее и наименьшее целое число

Fortran для меня совершенно новый, может ли кто-нибудь помочь мне решить проблему? Я хочу узнать все числа чисел целого числа и наибольшее и наименьшее значение для каждого типа номера на моем компьютере. У меня есть код, указанный ниже:

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 

Целые числа чисел, которые я получаю: 1,2,4,8.

  • Почему каждое наибольшее целое число для каждого типа числа одинаково: 2147483647? И есть ли внутренняя функция для наименьшего целого?

  • Как сохранить число целых чисел при вызове подпрограммы rang? Я думаю, что это ключ к наибольшему целому числу.

Ответ 1

Ваша подпрограмма:

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

принимает в качестве значения целочисленное значение по умолчанию и выводит наибольшее возможное значение, которое будет соответствовать целому числу по умолчанию. Он всегда будет возвращать огромное (по умолчанию целое число), которое на большинстве систем огромно (4-байтовое целое) или 2147483647. huge учитывает только тип переменной; он никак не интерпретирует переменную. Единственный способ, которым вы могли бы сделать то, что вы пытаетесь сделать выше, - это параметризованные производные типы, которые являются достаточно новыми, которые поддерживают его в компиляторах, все еще немного пятнистые.

Если вы хотите взглянуть на диапазоны разных KIND для INTEGER, вам придется использовать разные переменные:

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

Запуск дает:

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

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

Ответ 2

Чисто в качестве дополнения или альтернативной перспективы переменные Fortran определяются в терминах количества байтов памяти, выделенных для var. Действительно, все сопоставимые компиляторы определяют vars в терминах выделенных байтов, иначе было бы очень сложно для системы выделять/хранить в памяти, и очень сложно выполнить арифметику и т.д. Без нее.

Для некоторых, как и я, легче понять, что происходит, используя немного более старую нотацию (а не "рода konfusion". В частности, очень многие компиляторы обеспечивают прямое соответствие 1:1 между Kind и байтами /var, который затем делает вычисление самого большого/наименьшего целого достаточно простым (некоторые компиляторы используют нелинейное или непрямое соответствие). Хотя обязательно обратите внимание на поддержку переносимости в конце. Например

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

Аналогичное обозначение относится к другим типам Fortran (Real, Logical и т.д.). Все типы var имеют заданное по умолчанию количество байтов, если "размер" не указан.

Максимальное количество байтов для определенного типа также зависит от компилятора и системы (например, Integer (16) недоступен для всех систем и т.д.).

Байт имеет 8 бит, поэтому один байт должен иметь возможность разместить наибольшее значение 2 ^ 8 = 256, если нумерация от 1 или 255 начинается с 0.

Однако в Fortran (почти все) числовые вары "подписаны". Это означает, что где-то в битовом представлении требуется один бит для отслеживания, является ли это число + ve или число -ve. Таким образом, в этом примере max будет равен 2 ^ 7, поскольку один бит "потерян/зарезервирован" для "знаковой" информации. Таким образом, значения, доступные для подписанного 1-байтового целого числа, равны -127: +128 (обратите внимание на сумму Abs (пределы) до 255, так как "0" занимает одно место, всего 256 "вещей", так как это должно быть).

Аналогичное правило применяется для всех таких vars, просто с показателем "n", в 2 ^ n, изменяющимся в зависимости от количества байтов. Например, переменная Integer (8) имеет 8 байтов или 64 бита, причем 1 бит потерян/зарезервирован для информации о знаке, поэтому наибольшее возможное значение будет 2 ^ 63 = 9223372036854775808, если нумерация от 1 или = 4611686018427387904 при запуске от 0.

Стандартная модель данных Integer будет обобщена как:

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

где s = "знак" (+/- 1), w (k) является либо 1, либо 0 для k-го значения бит.

В объявлениях типов не обязательно использовать явные числа или env vars; разрешены определенные пользователем константы времени компиляции (т.е. параметры). Например

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.

Так как оператор Parameter может быть в другом модуле, доступном через Use и т.д., просто перекомпилировать большой сложный код для альтернативных определений "точности". Например, если DP отредактирован в Kind (1.0), то везде, где применяется эта декларация, становится "единственной точностью" Real.

Встроенные функции Fortran Huge(), Tiny() и т.д. помогают определить, что возможно в данной системе.

Гораздо больше может быть выполнено с помощью "бит-бит" Fortran и других инструментов/методов.