IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Fortran Discussion :

Récupérer des réels non NaN dans un fichier


Sujet :

Fortran

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 31
    Points : 26
    Points
    26
    Par défaut Récupérer des réels non NaN dans un fichier
    Bonjour,

    je rencontre un problème depuis un certains temps :
    en appliquant plusieurs fois une fonction qui renvoie normalement un réel,
    j'obtiens parfois la valeur NaN (Not a number) sans explications.

    Je stocke à chaque appel de la fonction la valeur obtenue dans un fichier text graĉe à
    WRITE(unit=10, file = ....
    Ainsi à la fin le fichier contient, en colonne, des réels, mais aussi des NaN :
    ça ressemble à ceci :

    24323
    0.45261277E-9
    NaN
    0.11112345E-5
    NaN
    NaN

    etc....

    Je souhaiterais créer une fonction qui récupère dans ce fichier
    uniquement les valeurs réelles (non NaN) et les stocke dans un vecteur VECTREELS.


    Ainsi je fait (pseudo algo) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    OPEN FICHIER.TXT
    i=1
    DO
    READ(10,iostat=io) valeur
    if (valeur /= "NaN") then
    VECTREELS(i) = valeur
    end if
    if (io <0) exit
    i=i+1
    END DO
    
    MAis j'obtiens une erreur car Fortran me dit que "valeur" a le type réel et ne peut etre comparé à un type caractère ("NaN").
    J'ai trouvé sur le net une fonction isnan mais le problème c'est que dans le fichier NaN n'est plus vraiment un NaN mais une chaine de caractère.
    lors de la lecture du fichier, comment READ valeur considère valeur
    quand il met NaN dans valeur, sachant que valeur doit etre de type réel ?
    C'est à dir, quand je fais :

    READ(10,*) valeur
    dans le fichier, si il rencontre NaN, quelle valeur met-il dans valeur de type réel?

    J'ai cherché des heures sans succès pour récupérer uniquement des réels dans un fichiers. J'ai vu des fonctions comme transfer, ieor mais je comprends pas bien.
    En fait je voudrais afficher les données binaires de valeur apres chaque read pour voir comment est représenter le NaN en binaire pour pouvoir comparer cette données binaires avec les données binaires des réels.

    Plus généralement comment faire pour récupérer des données d'un type donné dans un fichier? par exemple récupérer uniquement les entièrs présents, uniquement les réels, ... ?

    Merci d'avance si vous trouvez ce difficile problème.

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    Citation Envoyé par jyloup Voir le message
    Bonjour,

    je rencontre un problème depuis un certains temps :
    en appliquant plusieurs fois une fonction qui renvoie normalement un réel,
    j'obtiens parfois la valeur NaN (Not a number) sans explications.

    Je stocke à chaque appel de la fonction la valeur obtenue dans un fichier text graĉe à
    WRITE(unit=10, file = ....
    Ainsi à la fin le fichier contient, en colonne, des réels, mais aussi des NaN :
    ça ressemble à ceci :

    24323
    0.45261277E-9
    NaN
    0.11112345E-5
    NaN
    NaN

    etc....

    Je souhaiterais créer une fonction qui récupère dans ce fichier
    uniquement les valeurs réelles (non NaN) et les stocke dans un vecteur VECTREELS.


    Ainsi je fait (pseudo algo) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    OPEN FICHIER.TXT
    i=1
    DO
    READ(10,iostat=io) valeur
    if (valeur /= "NaN") then
    VECTREELS(i) = valeur
    end if
    if (io <0) exit
    i=i+1
    END DO
    
    MAis j'obtiens une erreur car Fortran me dit que "valeur" a le type réel et ne peut etre comparé à un type caractère ("NaN").
    J'ai trouvé sur le net une fonction isnan mais le problème c'est que dans le fichier NaN n'est plus vraiment un NaN mais une chaine de caractère.
    lors de la lecture du fichier, comment READ valeur considère valeur
    quand il met NaN dans valeur, sachant que valeur doit etre de type réel ?
    Il n'y a effectivement pas de conversion (lecture) de ce type de chaîne. De la même façon, tu ne pourrais pas lire "+Inf" avec un réel. La solution à ce type de situation consiste à séparer la lecture (chargement en mémoire) de la conversion (passage d'une chaîne de caractères à un nombre).

    Concrètement, ton programme doit être modifié comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    character (16) Chaine
    ...
    i=1
    DO
       READ(10,iostat=io,'(a)') Chaine
       if (io <0) exit
       if (Chaine /= "NaN") then
          read(Chaine,*) VECTREELS(i)
          i=i+1
       end if
    END DO
    Je ne suis pas certain et je n'ai pas de compilateur sous la main, mais je crois que le programme suivant fonctionne aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ...
    i=1
    DO
       READ(10,iostat=io,*) VECTREELS(i)
       if (io <0) exit
       i=i+1
    END DO
    (Je crois que le programme sautera simplement les lignes contenant des valeurs invalides (NaN)).

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 31
    Points : 26
    Points
    26
    Par défaut ne fonctionnent pas
    Bonjour

    merci pour votre aide mais aucune des 2 routines ne fonctionnent

    la première me renvoie une erreur à la ligne
    read(Chaine,*) vectreels(i)

    pourtant j'ai bien déclaré Chaine en CHARACTER
    et vectreels en vecteur de réels...

    la deuxieme renvoie les NaN quand je fais PRINT vectreels

    Pourriez-vous tester ces routines stp ?

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 152
    Points : 191
    Points
    191
    Par défaut
    Salut,

    Cette version-ci du programme marche (je viens de la tester)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    program TEST
    	integer :: io,I
    	character(99) :: CHAINE
    	real(kind=8),dimension(3) :: VECTREELS
    	i=1
    	open(10,file='TEST.txt',status='old',action='read')
    	DO
    	   READ(10,'(a)',iostat=io) Chaine
    	   if (io <0) exit
    	   if (trim(adjustl(Chaine)) /= "NaN") then
    	      print*,trim(adjustl(CHAINE))
    	      read(Chaine,*) VECTREELS(i)
    	      i=i+1
    	   end if
    	END DO
    	print*,VECTREELS
    end program TEST
    Attention à bien allouer le vecteur VECTREELS à la bonne taille par contre.

    En espérant t'avoir aidé,

    Marlan

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 31
    Points : 26
    Points
    26
    Par défaut
    Bonjour,

    tout d'abord merci pour votre code (c'était quand meme compliqué avec les trim et adjustl).

    Si maintenant le fichier contient des mots quelconques à la place de "NaN",
    est-il possible de récupérer uniquement les réels?

    En fait, je voudrais récupérer les éléments d'un type donné dans
    le fichier texte. (ici les réels, pas les chaînes de caractères).

    Y a-t-il un moyen de connaître le type d'un élément sur chaque ligne
    du fichier? (évidemment dans le cas ou les types ne sont pas mélangés,
    avec à la fois un réel et un mot sur la même ligne)

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 488
    Points : 593
    Points
    593
    Par défaut
    Bonjour,

    Si maintenant le fichier contient des mots quelconques à la place de "NaN",
    est-il possible de récupérer uniquement les réels?
    Oui, car on peut tester si une lecture s'est correctement déroulée via l'argument optionnel "iostat" de read() (c'est d'ailleurs que le fait Marlan, mais pour tester si on a réussi à lire une chaîne de caractères); la valeur de "iostat" renvoyée après la lecture sera 0 (zéro) si le type attendu a été lu.
    En repartant de l'exemple de Marlan, au lieu de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	   if (trim(adjustl(Chaine)) /= "NaN") then
    	      print*,trim(adjustl(CHAINE))
    	      read(Chaine,*) VECTREELS(i)
    	      i=i+1
    	   end if
    on peut faire quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
               real(kind=8) :: tmpval ! variable intermediaire pour stocker un reel
    ...
    	   read(Chaine,*,iostat=io) tmpval ! on tente de lire un reel
    	   if (io==0) then
    	      ! puisque le lecture s'est bien passee, on stocke la valeur lue dans VECTREELS(i)
                  VECTREELS(i)=tmpval
                  i=i+1
    	   end if

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 152
    Points : 191
    Points
    191
    Par défaut
    Salut,

    Je t'ai bidouillé un programme qui lit :
    1. Le nombre de la ligne, si la ligne ne contient qu'un nombre (ie : il ne stocke pas les lignes contenant uniquement des character)

    2. Si la ligne contient des character et un nombre ensuite, il lit le nombre mais l'unique condition que le séparateur entre la chaine de character et le nombre d'une ligne à une autre soit toujours de la même taille.

    Le fichier que j'ai utilisé ici est le suivant :

    24323
    0.45261277E-9
    NaNdvfvdfvd 10
    0.11112345E-5
    NaN
    NaN 10
    sdqkqdsd
    10

    Le programme en lui même est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    program TEST
    	implicit none
    	integer :: ios,I,K,J,TAILLE_SEPARATEUR=1,IMIN,IEND
    	character(99) :: CHAINE
    	character(1) :: COMPAR
    	real(kind=8),allocatable,dimension(:) :: VECTREELS,VECTREELS_TMP
    	logical :: ISTART,ISA_NUMBER
    	I=0
    	open(11,file='TEST.txt',status='old',action='read')
     
    	do
    		read(11,*,iostat=ios)
    		if(ios/=0)exit
    		I=I+1
    	end do
    	rewind(11)
     
    	allocate(VECTREELS_TMP(I))
    	I=1
    	DO
    		READ(11,'(a)',iostat=ios) CHAINE
    		if (ios /= 0) exit
     
    		ISTART=.FALSE.
    		ISA_NUMBER=.FALSE.
    		IEND=0
    		IMIN=0
     
    		do K=1,LEN(CHAINE)
    			if(.NOT. ISA_NUMBER) then
    				do J=0,9
    					write(COMPAR,'(i0)')J
    					if(COMPAR==CHAINE(K:K)) ISA_NUMBER=.TRUE.
    				end do
    			end if
     
    			if(CHAINE(K:K)=='' .and. .not. ISTART)then
    				ISTART=.TRUE.
    				IMIN=K+TAILLE_SEPARATEUR
    			end if
    			if(CHAINE(K:K+TAILLE_SEPARATEUR)=='' .and. ISTART) then
    				IEND=K-1
    				exit
    			end if
    		end do
     
    		if(ISA_NUMBER .and. IMIN<IEND) then
    			read(CHAINE(IMIN:IEND),*) VECTREELS_TMP(I)
    			I=I+1
    		end if
    		if(ISA_NUMBER .and. IMIN>IEND) then
    			read(CHAINE,*) VECTREELS_TMP(I)
    			I=I+1
    		end if
    	END DO
    	!REALLOCATION DU TABLEAU
     
    	allocate(VECTREELS(I-1))
    	VECTREELS=VECTREELS_TMP(1:I-1)
    	deallocate(VECTREELS_TMP)
    	print*,VECTREELS
    end program TEST
    En espérant avoir répondu à ta question,

    Marlan

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 31
    Points : 26
    Points
    26
    Par défaut donc c'était possible
    Wow on peut dire que vous avez été très efficace à résoudre mon problème, je suis très satisfait de cette réponse et vous en remercie.

    Donc maintenant je sais qu'il est possible de distinguer les types réels/ non réels dans un fichier,
    mais avouez qu'il fallait vraiment creuser dans les fonctions Fortran
    (utilisation de iostat en particulier) pour deviner ce code pas évident a priori.

    dommage qu'il n'existe pas tout simplement de fonction "typeof(x)"
    pour connaître le type de x dans un fichier (réel seul, chaine de characters
    uniquement, entier uniquement, etc...).

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 152
    Points : 191
    Points
    191
    Par défaut
    ^^

    En effet, la manipulation des fichiers en FORTRAN peut être assez délicate, surtout lorsque l'on a pas connaissance de l'ordre dans lequel ceux ci sont écris.

    N'oublies pas de cliquer sur l'onglet résolu en bas de page dès fois que quelqu'un ait le même problème à l'avenir.

    Bonne journée,

    Marlan

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2003] récupérer valeur d'une cellule, dans plusieurs fichiers placés dans des sous-dossiers
    Par greenfire15 dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 07/08/2012, 09h42
  2. Dernière ligne non vide, dans un fichier contenant des plans.
    Par Faelucc dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 01/07/2010, 13h27
  3. Récupérer des infos précise (nombre) dans un fichier texte
    Par the_magik_mushroom dans le forum Débuter
    Réponses: 11
    Dernier message: 07/06/2009, 09h56
  4. Réponses: 7
    Dernier message: 17/09/2008, 15h04
  5. Récupérer des lignes non enregistrées dans une table
    Par leddy dans le forum Langage SQL
    Réponses: 2
    Dernier message: 24/04/2008, 15h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo