Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 9 sur 9
  1. #1
    Candidat au titre de Membre du Club
    Inscrit en
    avril 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : avril 2009
    Messages : 31
    Points : 12
    Points
    12

    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 :
    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
    838
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : août 2006
    Messages : 838
    Points : 1 077
    Points
    1 077

    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 :
    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 :
    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 :
    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
    Candidat au titre de Membre du Club
    Inscrit en
    avril 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : avril 2009
    Messages : 31
    Points : 12
    Points
    12

    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é
    Inscrit en
    mai 2010
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : mai 2010
    Messages : 122
    Points : 121
    Points
    121

    Par défaut

    Salut,

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

    Code :
    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
    Candidat au titre de Membre du Club
    Inscrit en
    avril 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : avril 2009
    Messages : 31
    Points : 12
    Points
    12

    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 éprouvé
    Inscrit en
    mars 2007
    Messages
    370
    Détails du profil
    Informations forums :
    Inscription : mars 2007
    Messages : 370
    Points : 448
    Points
    448

    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 :
    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 :
    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é
    Inscrit en
    mai 2010
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : mai 2010
    Messages : 122
    Points : 121
    Points
    121

    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 :
    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
    Candidat au titre de Membre du Club
    Inscrit en
    avril 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : avril 2009
    Messages : 31
    Points : 12
    Points
    12

    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é
    Inscrit en
    mai 2010
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : mai 2010
    Messages : 122
    Points : 121
    Points
    121

    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.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •