🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: fr.comp.lang.c
Article #15415

Re: virgule flottante et FLT_EPSILON

#15415
From: Antoine Leca
Date: Tue, 27 Sep 2005 09:30
113 lines
5886 bytes
En <news:43386482$0$26880$626a14ce@news.free.fr>,
 Julien � Tribulations Parall�les � va escriure:
> En effet, en essayant le petit programme ci-dessous, on se rend
> compte que x=15, y=14.

[ Les questions sont report�es plus bas ]

Pas forc�ment.

> int main(void) {
>     float t2=1.5, t1=0.0, h=0.1;

Trois variables. En supposant une impl�mentation des flottants en binaire
(le plus courant, le cas base 16 est similaire, et en base 10 il n'y a pas
de probl�mes apparents), t2 et t1 sont des nombres exacts, mais h est un
rationel (mal repr�sent�, exactement comme 1/3 en d�cimal, car 5 n'est pas
un diviseur de 2).


>     int x=(1.5-0.0)/0.1;

� droite du =, on a une expression en double ; 1.5-0.0 va valoir 1.5 sur
toutes les impl�mentations, mais la division suivante par le nombre rationel
0.1+e (o� e est inf�rieur en valeur absolue � l'epsilon des double rapport�
� 0.1, mais non nul) va donner un r�sultat proche de 15 mais �ventuellement
diff�rent (et selon les arrondis cela peut �tre inf�rieur ou sup�rieur ou
�gal � 15).
Ensuite on applique l'op�rateur = qui fait une conversion vers un entier,
donc arrondi par d�faut (vers 0) ; on peut trouver suivant les
impl�mentations 14 ou 15 dans x.


>     int y=(t2-t1)/h;

� droite du =, on a des floats, que le compilateur peut _�ventuellement_
calculer avec une pr�cision inf�rieure. Les m�mes explications s'appliquent,
mais la valeur de h est maintenant 0.1+f, o� f est inf�rieur en valeur
absolue � l'epsilon des float rapport� � 0.1 (donc plus grand que le e
ci-dessus).
L� encore, le r�sultat sera de l'ordre de 15, selon les arrondis, inf�rieur
ou sup�rieur ou �gal � 15. Parce que � l'erreur � sur h est plus grande,
l'intervalle des valeurs possibles est plus important, donc dans les faits
tu peux avoir une plus grande variabilit�.
Ensuite m�me processus, conversion en entier donc arrondi par d�faut et on
se retrouve avec 14 ou 15.


>     int y_corrected=(t2-t1+FLT_EPSILON)/h;

M�me principe. Tu ajoute une petite quantit� ce qui force g�n�ralement le
r�sultat � remonter au-dessus de 15, mais le terme de seconde ordre (au
maximum, h vaut 0.1+FLT_EPSILON*10) doit permettre � certains cas rares
d'�tre en dessous de 15.0 (enfin, je n'ai pas pos� l'�quation, il faut bien
que tu fasses quelque chose ;-)).



> Afin de r�ellement obtenir 15,

Si tu veux _r�ellement_ obtenir 15, arr�tes d'utiliser des flottants et
passe � un autre syst�me de num�ration, virgule fixe ou bignums. Les
flottants sont un moyen rapide d'obtenir des r�sultats num�riques, ce ne
sont pas des concepts math�matiques fiables.


> 1- x et y me semblent identiques au premier abord.

� chaque fois que tu vois une constante ou une variable flottante, au lieu
de penser avec des nombres r�els en t�te (cela vaut 1.5 ou 0.1), pense que
cela repr�sente un intervalle de valeurs.

> Que se passe-t-il de diff�rent dans ces deux cas?

L'amplitude de l'intervalle des float est plus grande que celle des double.

> Pourquoi passer par des noms de variable semble changer la donne?

Parce que tu as typ� tes variables.
Si tu supprimes tes variables, tu as �crit

      int x=(1.5 -0.0 )/0.1;
      int y=(1.5f-0.0f)/0.1f;

Penses-tu toujours que c'est identique...


> 2- Quelle d�marche employer pour obtenir la bonne valeur?

Ne pas utiliser les flottants (et encore moins les convertir en entiers).


> Rajouter au num�rateur FLT_EPSILON comme je l'ai fait constitue-t-il une
bonne solution?

Non, c'est un empl�tre sur une jambe de bois. En plus, je ne suis pas s�r
que ce soit suffisant (cf. supra) : il faudrait calculer l'epsilon global de
l'expression (la largeur de l'intervalle du r�sultat), qui d�pend
compl�tement des expressions.

Le conseil de rajouter 0.5 avant de convertir en entier te permet d'�chapper
aux probl�mes d'arrondi aux limites (ceux que tu rencontres ici), en for�ant
l'utilisation d'un arrondi � normal � (� l'entier le plus proche) plut�t que
l'arrondi par d�faut (pour les nombres positifs) utilis� normalement en C :
ici, c'est un marteau pilon pour �craser une mouche, mais au moins cela te
permet de faire des calculs approximatifs en flottants et d'obtenir un
r�sultat entier (tant que tu ne d�passes pas la capacit� de la mantisse, et
en faisant attention � ajouter 0.5 pour les valeurs sup�rieures � 0.5 mais �
le soustraire pour celles qui sont inf�rieures � -0.5), quand tu sais que
c'est cela que tu cherches.



Antoine
Technical Details
Message-ID: <dhb3er$dg7$1@shakotay.alphanet.ch>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!news.glorb.com!news.cs.univ-paris8.fr!proxad.net!freenix!news.alphanet.ch!alphanet.ch!not-for-mail
References: <43386482$0$26880$626a14ce@news.free.fr>

Show Full Headers
Complete Article Headers
X-Google-Thread: f9822,309c5052b3bcc1bf
X-Google-Attributes: gidf9822,public
X-Google-Language: FRENCH,ASCII
Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!news.glorb.com!news.cs.univ-paris8.fr!proxad.net!freenix!news.alphanet.ch!alphanet.ch!not-for-mail
From: "Antoine Leca" <root@localhost.invalid>
Newsgroups: fr.comp.lang.c
Subject: Re: virgule flottante et FLT_EPSILON
Date: Tue, 27 Sep 2005 11:30:01 +0200
Organization: Posted through ALPHANET (http://www.alphanet.ch/)
Lines: 114
Sender: antoinel@143.red-217-127-250.staticip.rima-tde.net
Message-ID: <dhb3er$dg7$1@shakotay.alphanet.ch>
References: <43386482$0$26880$626a14ce@news.free.fr>
NNTP-Posting-Host: 143.red-217-127-250.staticip.rima-tde.net
Mime-Version: 1.0
Content-Type: text/plain;
 charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
X-Trace: shakotay.alphanet.ch 1127813403 13831 217.127.250.143 (27 Sep 2005 09:30:03 GMT)
X-Complaints-To: usenet@alphanet.ch
NNTP-Posting-Date: Tue, 27 Sep 2005 09:30:03 +0000 (UTC)
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1506
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1506