Fortran: целое число * 4 против целого числа (4) против целого числа (вид = 4) - PullRequest
50 голосов
/ 03 июля 2010

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

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

Ответы [ 3 ]

51 голосов
/ 03 июля 2010

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

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

Определив 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 содержит документацию под "внутренними модулями".

24 голосов
/ 24 июля 2014

Еще одно явное объяснение, что это за вид.Компилятор имеет таблицу разных числовых типов.Все целочисленные типы различны виды базового типа - 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.

Чтобы увидеть правильные варианты установки добрых чисел, см. Ответ MSB.

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

1 голос
/ 14 октября 2018

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


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

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


  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, который имел функции для запроса размера хранилища типов, реализованных компилятором, с такими встроенными функциями, как numeric_storage_size и bit_size. Еще одним дополнением к редакции Fortran 2003 был встроенный модуль iso_c_binding, который предоставлял значения параметров вида, чтобы гарантировать совместимость с типами C в отношении хранения, точности и диапазона.

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


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

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

...