Précédent   Forum du club des développeurs et IT Pro > Autres langages > Autres langages > Fortran
Fortran Forum d'entraide sur la programmation en Fortran. Avant de poster -> FAQ Fortran
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 23/11/2012, 05h42   #1
jyloup
Candidat au titre de Membre du Club
 
Inscription : 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.
jyloup est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/11/2012, 02h42   #2
Sylvain Bergeron
Modérateur
 
Inscription : août 2006
Messages : 781
Détails du profil
Informations personnelles :
Localisation : Canada

Informations forums :
Inscription : août 2006
Messages : 781
Points : 1 028
Points : 1 028
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)).
Sylvain Bergeron est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/11/2012, 10h05   #3
jyloup
Candidat au titre de Membre du Club
 
Inscription : 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 ?
jyloup est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/11/2012, 14h27   #4
Marlan
Membre habitué
 
Inscription : mai 2010
Messages : 111
Détails du profil
Informations forums :
Inscription : mai 2010
Messages : 111
Points : 109
Points : 109
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
Marlan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/12/2012, 17h50   #5
jyloup
Candidat au titre de Membre du Club
 
Inscription : avril 2009
Messages : 31
Détails du profil
Informations forums :
Inscription : avril 2009
Messages : 31
Points : 12
Points : 12
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)
jyloup est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/12/2012, 08h14   #6
Ehouarn
Membre éclairé
 
Inscription : mars 2007
Messages : 326
Détails du profil
Informations forums :
Inscription : mars 2007
Messages : 326
Points : 378
Points : 378
Bonjour,

Citation:
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
Ehouarn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/12/2012, 09h00   #7
Marlan
Membre habitué
 
Inscription : mai 2010
Messages : 111
Détails du profil
Informations forums :
Inscription : mai 2010
Messages : 111
Points : 109
Points : 109
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
Marlan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/12/2012, 12h48   #8
jyloup
Candidat au titre de Membre du Club
 
Inscription : 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...).
jyloup est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2012, 08h31   #9
Marlan
Membre habitué
 
Inscription : mai 2010
Messages : 111
Détails du profil
Informations forums :
Inscription : mai 2010
Messages : 111
Points : 109
Points : 109
^^

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
Marlan est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 17h44.


 
 
 
 
Partenaires

Hébergement Web