Подтвердить что ты не робот

Fortran: integer * 4 vs integer (4) vs integer (kind = 4)

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

  • integer*4
  • integer(4)
  • integer(kind=4)
4b9b3361

Ответ 1

В Fortran> = 90 лучшим подходом является использование встроенных функций для определения необходимой точности - это гарантирует как портативность, так и то, что вы получаете необходимую точность. Например, чтобы получить целые числа i и my_int которые будут поддерживать не менее 8 десятичных цифр, вы можете использовать:

integer, parameter :: RegInt_K = selected_int_kind (8)
integer (kind=RegInt_K) :: i, my_int

Определив RegInt_K (или любое RegInt_K имя, которое вы выберете) в качестве parameter, вы можете использовать его в своем коде как символ. Это также позволяет легко изменять точность.

При запросе 8 или 9 десятичных цифр обычно получается 4-байтовое целое число.

integer*4 - это общее расширение, возвращающееся к старому FORTRAN для указания 4-байтового целого числа. Хотя этот синтаксис не является и никогда не был стандартным Fortran.

integer (4) или integer (RegInt_K) являются сокращением от integer (kind=4) или integer (kind=RegInt_K). integer (4) не совпадает с integer*4 и является непереносимым - языковой стандарт не определяет числовые значения видов. Большинство компиляторов используют kind=4 для 4-байтовых целых чисел - для этих компиляторов integer*4 и integer(4) будут предоставлять один и тот же целочисленный тип - но есть исключения, поэтому integer(4) непереносимо и его лучше избегать,

Подход к реалам аналогичен.

ОБНОВЛЕНИЕ: если вы не хотите указывать числовые типы с требуемой точностью, а вместо хранилища, которое они будут использовать, Fortran 2008 предоставляет метод. Реалы и целые числа могут быть определены числом битов памяти после use модуля ISO_FORTRAN_ENV, например, для 4-байтового (32-битного) целого числа:

use ISO_FORTRAN_ENV
integer (int32) :: MyInt

Руководство по gfortran содержит документацию под "внутренними модулями".

Ответ 2

Просто еще одно явное объяснение того, что это такое. Компилятор имеет таблицу разных числовых типов. Все целые типы - это разные типы базового типа - integer. Скажем, компилятор имеет 1 байт, 2 байта, 4 байта, 8 байтов и 16 байтов integer (или real). В таблице компилятор имеет индекс для каждого такого типа - этот индекс является номером вида.

Многие компиляторы выбирают эту нумерацию:

kind number    number of bytes
1              1
2              2
4              4
8              8
16             16

Но они могут выбрать любую другую нумерацию. Одна из очевидных возможностей -

kind number    number of bytes
1              1
2              2
3              4
4              8
5              16

Есть действительно компиляторы (по крайней мере g77 и NAG), которые выбирают этот подход. Есть также варианты, чтобы изменить это. Поэтому числа kind не переносимы integer(kind=4) или integer(4) означает целое число 4 байта или целое число в 8 байтов в зависимости от компилятора.

integer*4 переносится в том смысле, что он всегда означает 4 байта. Но, с другой стороны, он не переносится, потому что он никогда не был частью какого-либо стандарта. Программы, использующие это обозначение, недействительны Fortran 77, 90 или любой другой Fortran.

Чтобы увидеть правильные параметры, как установить номера видов, см. M.S.B. Ответ.

То же самое относится к типам данных real. См. параметр вида Fortran 90 (ответ mataap).

Ответ 3

Я сделаю ссылку на эту поучительную статью, недавно написанную @SteveLionel, и попытаюсь осветить некоторые детали, которых пока нет в других ответах:


  1. Синтаксис, показанный в integer*n или real*n был распространенным расширением, предоставленным компиляторами давным-давно, когда разные компьютерные архитектуры начали иметь разные конструкции для формата целых и действительных значений в памяти, где n был размером в байтах значение сохранено. Однако это ничего не говорит о диапазоне или точности этих значений: например, разные реализации 16-битного целого числа могут предоставлять разные диапазоны и предельные значения.

Размеры регистров могут составлять 8, 12, 16, 30, 32, 36, 48, 60 или 64 бита, некоторые машины CDC имеют целые числа с одним дополнением (допускается минус ноль для целого числа!), Строка PDP-11 имеет несколько различных плавающих форматы точек в зависимости от серии, IBM 360/370 имела "шестнадцатеричную нормализацию" для своей плавающей точки и т.д. [...] Эти расширения были настолько популярны, что многие программисты думали (и даже сегодня многие думают), что этот синтаксис является стандартным Fortran; это не так!


  1. Когда вышел Fortran 90, к языку были добавлены параметры kind, а также встроенные функции запросов (особенно kind, selected_int_kind и selected_real_kind, а также другие, такие как precision, digits, epsilon...), чтобы помочь программисту определить минимальные требования для точность и диапазон числовых типов (до сих пор нет официального упоминания модели хранения или байтов). Синтаксис - integer(kind=n) или даже integer(n), где n - постоянное значение, соответствующее виду целого числа, поддерживаемому компилятором. Для литеральных констант синтаксис 12_n или 3.4e-2_n.

    Преимущество этого решения состояло в том, что Fortran не делал (и до сих пор не делает) никаких предположений о деталях реализации типов данных, отличных от результатов функций запроса, используемых для выбора типа, поэтому код параметризируется проблема решается не языком или оборудованием. Гоча, как сказано в других ответах, каждый компилятор может выбирать свои добрые числа, таким образом предполагая, что магическое число, такое как integer(4), не является переносимым.


  1. Также с Fortran 90 появилась концепция видов по умолчанию, то есть то, что вы получаете, когда не указываете вид.

Типы по умолчанию зависели от реализации, хотя вплоть до Fortran 2008 компилятор должен был поддерживать только один целочисленный вид и два вещественных вида. (Это все еще верно в Fortran 2018, но есть дополнительное требование, чтобы по крайней мере один целочисленный вид поддерживал 18 десятичных цифр.) Если вы пишете константный литерал без спецификатора вида, вы получаете вид по умолчанию.


  1. С Fortran 2003 и включением встроенного модуля ieee_arithmetic вы можете запросить и выбрать реальный тип с возможностями IEEE с плавающей запятой, если это возможно.

Существуют архитектуры, в которых доступны как плавающие типы IEEE, так и не-IEEE, такие как HP (ранее Compaq или ранее DEC) Alpha. В этом случае вы можете использовать IEEE_SELECTED_REAL_KIND из встроенного модуля IEEE_ARITHMETIC для получения плавающего вида IEEE. А что, если нет поддерживаемого вида, отвечающего требованиям? В этом случае встроенные функции возвращают отрицательное число, которое (обычно в зависимости от контекста) вызывает ошибку во время компиляции.


  1. Наконец, в Fortran 2003 iso_fortran_env встроенный модуль iso_fortran_env, который имел функции для iso_fortran_env размера хранилища типов, реализованных компилятором, с такими встроенными bit_size как numeric_storage_size и bit_size. Еще одним дополнением к ревизии Fortran 2003 стал встроенный модуль iso_c_binding, предоставляющий значения параметров типа для гарантии совместимости с типами C в отношении хранения, точности и диапазона.

Внутренний модуль ISO_C_BINDING объявляет константы для типов Fortran, которые совместимы с типами C, например C_FLOAT и C_INT. Используйте их, если вы объявляете переменные и интерфейсы, совместимые с C.


  1. В качестве последнего замечания я упомяну недавний стандарт Fortran 2008, который расширил встроенный модуль iso_fortran_env включив в него именованные константы int8, int16, int32 m int64, real32, real64 и real128, значения которых соответствуют типам целых и вещественных типов, которые занимают указанное количество бит. Суть в том, что эти константы обеспечивают только размер хранилища, а не точность или диапазон. Используйте их только тогда, когда это именно то, что вы хотите.

На мой взгляд, это немного лучше, чем старое расширение * n в том смысле, что оно говорит о том, что тип подходит для такого количества битов, но больше ничего о нем. Например, есть один компилятор, в котором REAL128 хранится в 128 битах, но на самом деле представляет собой 80-битную реальную "расширенную точность", используемую в старых регистрах стека с плавающей запятой x86. Если вы используете их, вы можете подумать, что используете переносную функцию, но на самом деле это не так, и вас могут укусить, когда у того, кого вы получаете, нет необходимых вам возможностей.