J'essaie d'apprendre Fortran et je vois beaucoup de définitions différentes circuler et je me demande s'ils essaient d'accomplir la même chose. Quelle est la différence entre les éléments suivants?
integer*4
integer(4)
integer(kind=4)
Dans Fortran> = 90, la meilleure approche consiste à utiliser des fonctions intrinsèques pour spécifier la précision dont vous avez besoin - cela garantit à la fois la portabilité et que vous obtenez la précision dont vous avez besoin. Par exemple, pour obtenir des entiers i
et my_int
Qui prendront en charge au moins 8 chiffres décimaux, vous pouvez utiliser:
integer, parameter :: RegInt_K = selected_int_kind (8)
integer (kind=RegInt_K) :: i, my_int
Après avoir défini RegInt_K
(Ou le nom que vous sélectionnez) comme parameter
, vous pouvez l'utiliser dans votre code comme symbole. Cela facilite également la modification de la précision.
La demande de 8 ou 9 chiffres décimaux obtiendra généralement un entier de 4 octets.
integer*4
Est une extension courante remontant à l'ancien FORTRAN pour spécifier un entier de 4 octets. Cependant, cette syntaxe n'est pas et n'a jamais été Fortran standard.
integer (4)
ou integer (RegInt_K)
sont l'abréviation de integer (kind=4)
ou integer (kind=RegInt_K)
. integer (4)
n'est pas identique à integer*4
et n'est pas portable - la norme de langue ne spécifie pas les valeurs numériques des types. La plupart des compilateurs utilisent le kind=4
Pour les entiers de 4 octets - pour ces compilateurs integer*4
Et integer(4)
fourniront le même type d'entier - mais il y a des exceptions, donc integer(4)
n'est pas portable et est préférable de l'éviter.
L'approche pour les réels est similaire.
MISE À JOUR: si vous ne souhaitez pas spécifier les types numériques par la précision requise, mais plutôt par le stockage qu'ils utiliseront, Fortran 2008 fournit une méthode. les réels et les entiers peuvent être spécifiés par le nombre de bits de stockage après use
ing le module ISO_FORTRAN_ENV
, par exemple, pour un entier de 4 octets (32 bits):
use ISO_FORTRAN_ENV
integer (int32) :: MyInt
Le manuel de gfortran a une documentation sous "modules intrinsèques".
Juste une explication plus explicite de ce genre. Le compilateur a une table de différents types numériques. Tous les types entiers sont différents types du type de base - integer
. Disons que le compilateur a 1 octet, 2 octets, 4 octets, 8 octets et 16 octets integer
(ou real
). Dans le tableau, le compilateur a un index pour chacun de ce type - cet index est le numéro du type.
De nombreux compilateurs choisissent cette numérotation:
kind number number of bytes
1 1
2 2
4 4
8 8
16 16
Mais ils peuvent choisir n'importe quelle autre numérotation. L'une des possibilités évidentes est
kind number number of bytes
1 1
2 2
3 4
4 8
5 16
Il existe en effet des compilateurs (au moins g77 et NAG) qui choisissent cette approche. Il existe également des options pour changer cela. Par conséquent, les nombres kind
ne sont pas portables integer(kind=4)
ou integer(4)
signifie un entier de 4 octets ou un entier de 8 octets selon le compilateur.
integer*4
Est portable dans le sens où il signifie toujours 4 octets. Mais d'un autre côté, il n'est pas portable car il n'a jamais fait partie d'aucune norme. Les programmes utilisant cette notation ne sont pas des Fortran 77, 90 ou tout autre Fortran valides.
Pour voir les bonnes options sur la façon de définir les nombres, voir la réponse de M.S.B.
Le même concept s'applique aux types de données real
. Voir paramètre genre Fortran 9 (la réponse du mataap).
Je vais faire référence à cet article instructif , écrit récemment par @SteveLionel, et essayer de couvrir certains détails qui ne sont pas présents dans les autres réponses jusqu'à présent:
integer*n
Ou real*n
Était une extension courante fournie par les compilateurs il y a longtemps, lorsque différentes architectures informatiques ont commencé à avoir des conceptions différentes pour le format en mémoire des valeurs entières et réelles, où n
était la taille en octets de la valeur stockée. Cependant, cela ne dit rien sur la plage ou la précision de ces valeurs: différentes implémentations d'un entier 16 bits, par exemple, pourraient fournir différentes plages et valeurs limites.Les tailles de registre peuvent être 8, 12, 16, 30, 32, 36, 48, 60 ou 64 bits, certaines machines CDC avaient des entiers à complément un (permettant moins zéro pour un entier!), La ligne PDP-11 avait plusieurs flottants différents formats de points selon la série, l'IBM 360/370 avait une "normalisation hexadécimale" pour sa virgule flottante, etc. [...] Ces extensions étaient si populaires que de nombreux programmeurs pensaient (et même aujourd'hui beaucoup pensent) que cette syntaxe est la norme Fortran ; ce n'est pas!
Lorsque Fortran 90 est sorti, kind
paramètres ont été ajoutés au langage, ainsi que des fonctions de recherche intrinsèques (spécialement kind
, selected_int_kind
Et selected_real_kind
, Mais aussi d'autres , comme precision
, digits
, epsilon
...) pour aider le programmeur à spécifier les exigences minimales pour la précision et la plage de types numériques (toujours, aucune mention officielle du modèle de stockage ou des octets). La syntaxe est integer(kind=n)
ou même integer(n)
, où n
est une valeur constante correspondant à une sorte d'entier pris en charge par le compilateur. Pour les constantes littérales, la syntaxe est 12_n
Ou 3.4e-2_n
.
L'avantage de cette solution était que Fortran n'a pas (et ne fait toujours pas) d'hypothèses sur les détails d'implémentation des types de données autres que les résultats des fonctions d'interrogation utilisées pour choisir le type, donc le code est paramétré par le problème étant résolu, pas par la langue ou le matériel. Le gotcha est, comme dit dans d'autres réponses, chaque compilateur peut choisir ses nombres aimables, supposant ainsi que le nombre magique comme integer(4)
n'est pas portable.
Les types par défaut étaient dépendants de l'implémentation, bien que jusqu'à Fortran 2008, un compilateur ait été requis pour prendre en charge un seul type entier et deux types réels. (C'est toujours vrai dans Fortran 2018, mais il y a une exigence supplémentaire qu'au moins un type entier prend en charge 18 chiffres décimaux.) Si vous écrivez un littéral constant sans spécificateur de type, vous obtenez le type par défaut.
ieee_arithmetic
, Vous pouvez vous renseigner et sélectionner un type réel avec des capacités en virgule flottante IEEE, si disponible.Il existe des architectures où les types flottants IEEE et non-IEEE sont disponibles, comme l'alpha HP (anciennement Compaq anciennement DEC). Dans ce cas, vous pouvez utiliser IEEE_SELECTED_REAL_KIND à partir du module intrinsèque IEEE_ARITHMETIC pour obtenir un type flottant IEEE. Et si aucun type pris en charge ne répond aux exigences? Dans ce cas, les valeurs intrinsèques renvoient un nombre négatif qui déclenchera (généralement, selon le contexte) une erreur au moment de la compilation.
iso_fortran_env
, Qui avait des fonctions pour interroger la taille de stockage des types implémentés par un compilateur, avec intrinsèques comme numeric_storage_size
et bit_size
. Un autre ajout de la révision de Fortran 2003 était le module intrinsèque iso_c_binding
, Qui fournissait des valeurs de paramètres aimables pour garantir la compatibilité avec les types C, en stockage, précision et plage.Le module intrinsèque ISO_C_BINDING déclare des constantes pour les types Fortran qui sont interopérables avec les types C, par exemple C_FLOAT et C_INT. Utilisez-les si vous déclarez des variables et des interfaces interopérables avec C.
iso_fortran_env
Pour inclure les constantes nommées int8
, int16
, int32
M int64
, real32
, real64
Et real128
, Dont les valeurs correspondent aux types d'entiers et de types réels qui occupent le nombre de bits indiqué. Le problème est que ces constantes assurent uniquement la taille de stockage , pas la précision ou la plage. Utilisez-les uniquement lorsque c'est exactement ce que vous voulez.À mon avis, c'est un peu mieux que l'ancienne extension * n en ce qu'elle vous indique qu'un type tient dans autant de bits, mais rien d'autre à ce sujet. Par exemple, il y a un compilateur où REAL128 est stocké sur 128 bits mais est vraiment la "précision étendue" de 80 bits utilisée dans les anciens registres de pile à virgule flottante x86. Si vous les utilisez, vous pourriez penser que vous utilisez une fonctionnalité portable, mais en réalité vous ne l'êtes pas et vous risquez d'être mordu lorsque le type que vous obtenez n'a pas les capacités dont vous avez besoin.