Фортран: наибольшее и наименьшее целое число

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

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.

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

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

2 ответа

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

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

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

Если вы хотите взглянуть на диапазоны различных типов 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

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

Для некоторых, таких как я, легче увидеть, что происходит, используя немного более старую нотацию (а не "добрую конфузию"). В частности, очень многие компиляторы обеспечивают прямое соответствие 1:1 между Kind и bytes/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

Аналогичная запись применяется к другим типам Фортрана (Реальный, Логический и т. Д.). Все типы переменных имеют количество байтов по умолчанию, если "размер" не указан.

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

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

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

Аналогичное правило применяется ко всем таким переменным, причем просто показатель степени "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 в объявлениях типов; Определяемые пользователем константы времени компиляции (т.е. параметры) разрешены. Например

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), то везде, где применяется это объявление, оно становится "реальной точностью".

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

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

Другие вопросы по тегам