OVH Cloud OVH Cloud

comparaison de flottants

209 réponses
Avatar
Emmanuel
bonjour tout le monde,

une question de vrai débutant :

Avec le programme essai.c suivant

int main(void) {
return ((1.7 + 0.1) == 1.8) ? 1 : 0;
}

j'obtiens :

$ gcc -Wall -o essai essai.c; ./essai; echo $?
1

Avec le programme essai.c suivant

int main(void) {
float x;
x = 1.7;
return ((x + 0.1) == 1.8) ? 1 : 0;
}

j'obtiens :

$ gcc -Wall -o essai essai.c; ./essai; echo $?
0

Pourtant, le programme

#include <stdio.h>
int main(void) {
float x;
x = 1.7;
printf("%f et %f\n", 1.7 + 0.1, x + 0.1);
}

affiche :
1.800000 et 1.800000

Apparremment, 1.7+0.1 et x+0.1 sont égaux ; j'imagine qu'il s'agit d'un
problème de représentation des flottants en machine mais j'aimerais bien
avoir une confirmation ou une infirmation (et une explication, si possible).

Merci par avance.

Emmanuel

10 réponses

Avatar
Francois
Je n'y connais pas grand chose en C par rapport à vous tous
et je me contente d'essayer de suivre (en partie du moins)
ce fil. Mais je voulais juste apporter une précision à ceci
(car les maths je connais mieux) :

Samuel DEVULDER a écrit :

Je ne suis pas d'accord. Décimal ou binaire n'est absolument pas une
propriété intrinsèque d'un nombre. Un nombre est un truc qui existe
indépendamment de la façon de l'écrire. Est-ce que sqrt(2) est binaire
ou décimal? Ni l'un ni l'autre, par contre on peut le *représenter* avec
des chiffres binaires ou décimaux.



Je ne suis pas tout à fait d'accord ou alors il y a
ambiguïté sur le mot "décimal" (ou alors j'ai pas bien lu
tout le contexte du message et dans ce cas désolé pour mon
intervention). Pour moi, "décimal" a un sens mathématique :

Un nombre est "décimal" ssi c'est un réel de la forme
n/(10^k) avec n un entier relatif et k un entier naturel.

Par ailleurs, il y a "l'écriture décimale" d'un nombre qui
est la façon (pas forcément unique) de le représenter avec
des symboles appelés "chiffres", au même titre qu'il y a
"l'écriture binaire" d'un nombre.

En revanche, "un nombre binaire" n'a pas de sens pour moi du
point de vue mathématique.

Voilà. :-)


--
François Lafont
Avatar
Samuel DEVULDER
Francois a écrit :
Je n'y connais pas grand chose en C par rapport à vous tous et je me
contente d'essayer de suivre (en partie du moins) ce fil. Mais je
voulais juste apporter une précision à ceci (car les maths je connais
mieux) :

Samuel DEVULDER a écrit :

Je ne suis pas d'accord. Décimal ou binaire n'est absolument pas une
propriété intrinsèque d'un nombre. Un nombre est un truc qui existe
indépendamment de la façon de l'écrire. Est-ce que sqrt(2) est binaire
ou décimal? Ni l'un ni l'autre, par contre on peut le *représenter*
avec des chiffres binaires ou décimaux.



Je ne suis pas tout à fait d'accord ou alors il y a ambiguïté sur le mot
"décimal" (ou alors j'ai pas bien lu tout le contexte du message et dans



Oui je crois aussi qu'il y a d'ambiguïté, ou du moins un mélange entre
propriétés d'un nombre et sa représentation symbolique.

ce cas désolé pour mon intervention). Pour moi, "décimal" a un sens
mathématique :


Un nombre est "décimal" ssi c'est un réel de la forme n/(10^k) avec n un
entier relatif et k un entier naturel.



Mathématiquement, oui
(http://fr.wikipedia.org/wiki/Nombre_d%C3%A9cimal), mais cet aspect ne
figure pratiquement pas dans le concept des flottants informatiques
(pratiquement car il existe les BigDecimal en java qui sont exactement
ceux-là).

Par ailleurs vu qu'on en est à parler de ces types de nombres, j'ai
toujours eu du mal à y voir un intérêt mathématique particulier autre
que celui d'exister. Pour moi, ce ne sont plus ou moins qu'un sous
ensemble de Q sans grosses propriétés utiles. As tu connaissance de
théorèmes sur cet ensemble nombres? (à part les trucs triviaux d'être
dense dans |R, d'être stable par l'addition, multiplication, etc), bref
un théorème utile ou curieux? (cf les p-adiques ci-après)

Par ailleurs, il y a "l'écriture décimale" d'un nombre qui est la façon
(pas forcément unique) de le représenter avec des symboles appelés



le classique p.nnnnnn00000... = p.nnnnn(n-1)999999... ?

"chiffres", au même titre qu'il y a "l'écriture binaire" d'un nombre.



Oui, et dans le cadre du printf on parle évidemment de l'écriture. Il
n'y a rien d'autre qui compte à mon sens.

En revanche, "un nombre binaire" n'a pas de sens pour moi du point de
vue mathématique.



Peut être les nombres de la forme n/2^k par extension (qui ne
recouvrirait pas exactement l'ensemble des décimaux). Mais il y aurait
plus intéressante et proche de l'informatique en considérant les nombres
2-adiques (http://fr.wikipedia.org/wiki/Nombre_p-adique). Ces nombres là
sont une généralisation du complément-à-deux à l'infini si j'ai bien
compris (ils se poursuivent indéfiniment sur la gauche) . Le truc rigolo
avec eux, c'est que bien qu'ayant une écriture qui fait penser à des
entiers signés,

-1 = ...11111111

7 = ...00000111
-7 = ...11111001

ils peuvent en réalité représenter des nombres fractionnaires.

1/3 = ..010101011

(et même des racines carrées, ou des nombres transcendants: exp(4)).

sam.
Avatar
Vincent Lefevre
Dans l'article <hpj327$24uv$,
Marc Espie écrit:

In article <20100407160607$,
Vincent Lefevre wrote:

>Je trouve les typedef utiles pour les bibliothèques, afin de cacher
>l'implémentation interne à l'utilisateur, et afin de pouvoir changer
>(on évite tout de même) sans casser l'API.

... et tu fais comment pour etre sur que tes noms ne vont pas empieter
sur ceux des voisins dans les fichiers d'entete ?



On utilise un préfixe (e.g. mpfr_), ce qui résout le problème en
pratique. De toute façon, il y a exactement le même genre de problème
pour les noms de fonction, et c'est inévitable (je me vois mal fournir
une bibliothèque sans fonctions!). Idem pour les macros.

>> Par exemple, si je suis sous Unix, je peux tres bien ecrire:
>> pid_t fd = open("/etc/passwd", O_RDONLY);
>> et mon compilo ne bronchera pas...
>
>C'est une limite des typedef, qui ne définissent pas des nouveaux
>types. Ce n'est pas une raison pour ne pas les utiliser.

Si, c'est une raison. Ils n'apportent rien en terme de surete du code, et



Les typedef n'ont jamais été là pour la sureté du code.

--
Vincent Lefèvre - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)
Avatar
Manuel Pégourié-Gonnard
Samuel DEVULDER scripsit :

Francois a écrit :
Je n'y connais pas grand chose en C par rapport à vous tous et je me
contente d'essayer de suivre (en partie du moins) ce fil. Mais je
voulais juste apporter une précision à ceci (car les maths je connais
mieux) :

Samuel DEVULDER a écrit :

Je ne suis pas d'accord. Décimal ou binaire n'est absolument pas une
propriété intrinsèque d'un nombre. Un nombre est un truc qui existe
indépendamment de la façon de l'écrire. Est-ce que sqrt(2) est binaire
ou décimal? Ni l'un ni l'autre, par contre on peut le *représenter*
avec des chiffres binaires ou décimaux.



Je ne suis pas tout à fait d'accord ou alors il y a ambiguïté sur le mot
"décimal" (ou alors j'ai pas bien lu tout le contexte du message et dans



Oui je crois aussi qu'il y a d'ambiguïté, ou du moins un mélange entre
propriétés d'un nombre et sa représentation symbolique.



Je crois qu'on pourrait se mettre d'accord que le fait que la sens d'une
expression comme « nombre binaire » ou « nombre décimal » dépend du
contexte et relève purement d'une convention (comme un peu tout ce qui
relève du langage et des notations, en fait).

Du coup, à partir du moment où l'éventuelle ambiguïté de départ a été
levée, et que le sens est devenu clair, peut-être qu'il n'est plus très
utile de discuter trop longtemps ce point de pur vocabulaire ? D'autant
plus que ce faisant, on commence à dériver assez loin du C... (notez que
moi personnellement j'aime bien qu'on parle de nombres p-adiques, mais
je me demande quand même si c'est bien le lieu).

Par ailleurs vu qu'on en est à parler de ces types de nombres, j'ai
toujours eu du mal à y voir un intérêt mathématique particulier autre
que celui d'exister. Pour moi, ce ne sont plus ou moins qu'un sous
ensemble de Q sans grosses propriétés utiles.



Bah au niveau informatique, ce sont les nombres qui sont représentables
de façon exacte en mémoire (pour peu qu'ils n'excèdent pas les bornes)
dans un système dont la représentation interne utilise la base 10.

On trouve parfois l'expression « nombre diadique » (surtout dans les
vieux bouquins de prépa) pour désigner les nombres qui s'écrivent avec
un nombre fini de chiffres après la virgule en base 2. C'est une
expression que je n'aime pas trop, parce que j'ai peur que ça introduise
une confusion avec « nombre 2-adique » et que ces derniers sont quand
même vachement plus utiles.

As tu connaissance de
théorèmes sur cet ensemble nombres? (à part les trucs triviaux d'être
dense dans |R, d'être stable par l'addition, multiplication, etc), bref
un théorème utile ou curieux? (cf les p-adiques ci-après)



Personnellement, je n'ai pas connaisance de résultats mathématiques
là-dessus, et je doute qu'il y a des trucs passionants en effet.

Par ailleurs, il y a "l'écriture décimale" d'un nombre qui est la façon
(pas forcément unique) de le représenter avec des symboles appelés



le classique p.nnnnnn00000... = p.nnnnn(n-1)999999... ?



Bah vu le contexte, je suppose qu'on parlait d'écriture finie. (Encore
et toujours le contexte.)

Peut être les nombres de la forme n/2^k par extension (qui ne
recouvrirait pas exactement l'ensemble des décimaux).



Je ne les jamais vus appellés « nombres binaires » nulle part, mais
parfois « nombres diadiques » comme je disais ci-dessus.

Mais il y aurait
plus intéressante et proche de l'informatique en considérant les nombres
2-adiques (http://fr.wikipedia.org/wiki/Nombre_p-adique). Ces nombres là
sont une généralisation du complément-à-deux à l'infini si j'ai bien
compris (ils se poursuivent indéfiniment sur la gauche) .



Effectivement, si on veut les écrire sous la forme d'un développement
« décimal » (dans le sens « une suite de chiffres avec une virgule »,
comme quoi ce mot a décidément plein de sens différents), la partie
après la virgule sera finie, mais pas forcément celle avant.

Le truc rigolo
avec eux, c'est que bien qu'ayant une écriture qui fait penser à des
entiers signés,



Pour tes exemples, oui, mais en général l'écriture ne fait pas penser à
des entiers :

1/2 = 0.1
1.75 = 1.11

L'ensemble des nombres 2-adiques qui ont un développement fini
(sous-entendu à gauche) coïncide avec l'ensemble des nombres qu'on
appelait « diaques » ci-dessus.

-1 = ...11111111

7 = ...00000111
-7 = ...11111001



Note que c'est assez analogue (modulo le signe) au problème plus
classique de non-unicité du développement décimal (classique) des
nombres décimaux : 1 = 0.99999999...

ils peuvent en réalité représenter des nombres fractionnaires.

1/3 = ..010101011

(et même des racines carrées, ou des nombres transcendants: exp(4)).



Tout pareil que les nombres réels sur ces points :-)

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
Avatar
Jean-Marc Bourguet
Vincent Lefevre writes:

Dans l'article <hphoa4$1ldm$,
Marc Espie écrit:

Quand j'enseigne le C, je deconseille totalement l'utilisation de typedef
sauf des cas parfaitement definis (en gros, typedef pour les types de
pointeur de fonction, parce que sinon c'est vraiment imbitable).



Et pour les enum, et pour les structures?



Là c'est un choix purement stylistique à mon avis. Et je fais trop de C++
pour ne pas être à l'aise le code qui fait systématiquement

typedef struct x x;

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Antoine Leca
Vincent Belaïche écrivit :
J'avais ajouté la dernière colonne parce que la discussion était partie
sur ce que veut dire "binaire" ou "décimal" lorsque on parle de nombre
binaire ou de nombre "décimal".



Voui.

Je maintiens que, en français, lorsque on applique cette épithète au mot
nombre, on fait référence à ses propriétés mathématiques,



C'est juste une tautologie, une reformulation, non?
On ne parle pas ici des nombres décimaux au sens de ceux qui ont une
représentation finie en base dix (l'ensemble habituellement écrit "ID")

qui en dernier ressort dépendent de la façon dont il est mémorisé dans
la machine.



Euh, non. Ou alors, seulement partiellement.

Il y a deux choses pour moi distinctes. L'un est le programme, et sa
signification (putative lorsqu'on prend le point de vue du programmeur,
partiellement définie lorsqu'on prend le point de vue de la norme,
totalement définie lorsqu'on prend le point de vue d'un compilateur).

Une autre chose est la représentation sur une machine donnée de ce
programme.

C'est évidemment la même chose lorsqu'on considère une partie du
programme, comme par exemple un nombre flottant qu'il manipule.


Un exemple ici est celui des machines qui manipulent les nombres
flottants en base 10 : comme au final ces machines sont électroniques,
le nombre en base 10 sera à la fin représenté par un ensemble d'états
binaires (normalement en BCD) ; quel est donc la base « en mémoire » ?
Et en quoi le fait de répondre 10 ou 2 change quoi que ce soit ?


Toujours est-il que je maintiens aussi que dans "binary exponent part",
"binary" est en rapport avec la base de logarithme utilisée pour la
repésentation textuelle avec %a



Plus exactement (et c'est exactement ce que décrit la norme), dans une
représentation de la forme m×2^e, avec de plus certaines propriétés
spécifiées concernant les relations entre cette représentation
intermédiaire et d'une part la représentation textuelle, d'autre part la
(ou les) véritables représentations machine.


et non avec le fait que l'exposant est
en général un nombre binaire, c'est à dire avec une base de numération 2
en mémoire (par ex. sur une machine où la dernière colonne est vraie).



Mouais. D'un autre côté, ce serait se mettre la tête dans le sable que
d'imaginer que la représentation hexadécimale des nombres flottants et
le spécificateur %a n'ont rien à voir avec le fait que la très grande
majorité des machines utilisent la base 2 (et non la base 10) pour
représenter les flottants.



Antoine
Avatar
Antoine Leca
Samuel DEVULDER écrivit :
En fait binaire ou décimal ne s'applique qu'aux chiffres et pas aux
nombres.



Non, ou du moins non dès que l'on s'éloigne des mathématiques « pures »
et que l'on rajoute les contraintes de représentation, qui sont au cœur
du sujet (et dans le titre).

D'abord, il y a le cas des nombres décimaux (représentables en base dix
par un nombre fini de chiffres, ou tq il existe une forme n/10^k.)
Évidemment, on peut définir de la même façon des nombres « binaires »
(je mets des guillemets car c'est un néologisme) à partir de la base 2.

Une sous catégorie de ces nombres sont les nombres dits « fixes », pour
lesquels k est fixé (et pour une base elle aussi déterminée, normalement
deux ou dix), et où n appartient à un certain intervalle. Le cas
classique, c'est celui des comptabilités en centimes (k=2, base dix).

Ensuite, en ce qui concerne les nombres flottants, les deux éléments n
et k peuvent appartenir à deux intervalles (qui définissent le type), et
dans cette expression la base est encore une fois un fondement
déterminant ; et les propriétés des nombres changent (surtout en ce qui
concerne les arrondis) en fonction de la base.

Un autre élément important, c'est que l'on ne peut passer arbitrairement
d'une base à une autre (et c'est justement la raison d'être de %a).
C'est beaucoup plus facile de changer les intervalles (même si cela crée
des problèmes subtils d'arrondis).


Tout cela ne concerne que les nombres, pas leurs représentation, que ce
soit en mémoire, en machine ou sous forme textuelle, qui font partie
d'un autre niveau.


Antoine
Avatar
Vincent Lefevre
Dans l'article ,
Jean-Marc Bourguet écrit:

Vincent Lefevre writes:

> Dans l'article <hphoa4$1ldm$,
> Marc Espie écrit:
>
>> Quand j'enseigne le C, je deconseille totalement l'utilisation de typedef
>> sauf des cas parfaitement definis (en gros, typedef pour les types de
>> pointeur de fonction, parce que sinon c'est vraiment imbitable).
>
> Et pour les enum, et pour les structures?

Là c'est un choix purement stylistique à mon avis. Et je fais trop de C++
pour ne pas être à l'aise le code qui fait systématiquement

typedef struct x x;



Euh... je ne suis pas favorable à ce que fait C++, mais il y a le
même genre de problème entre "struct x" et un typedef. Par exemple,
si une raison de rejeter les typedef est les conflits entre en-têtes,
il en est de même pour les structures nommées. Dit autrement, définir
une structure nommée est très similaire à un typedef; la seule
différence est que dans le cas du typedef, on a un seul identifieur,
alors que dans le cas de la structure, on a un nom de la forme
"struct identifieur".

--
Vincent Lefèvre - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)
Avatar
Vincent Lefevre
Dans l'article <hpk5ot$fdr$,
Antoine Leca écrit:

Un exemple ici est celui des machines qui manipulent les nombres
flottants en base 10 : comme au final ces machines sont électroniques,
le nombre en base 10 sera à la fin représenté par un ensemble d'états
binaires (normalement en BCD) ; quel est donc la base « en mémoire » ?
Et en quoi le fait de répondre 10 ou 2 change quoi que ce soit ?



Dans la norme IEEE 754-2008, il y a deux représentations (ou plutôt,
encodages) possibles pour les flottants décimaux:
* l'une (a.k.a. BID), provenant d'Intel, où le significande est
encodé entièrement en base 2, le but étant de réutiliser le FPU
des flottants binaires (cas notamment des implémentations en
soft);
* l'autre (a.k.a. DPD), provenant d'IBM, où le significande est
encodé en base 10 sous forme compacte: 3 chiffres décimaux dans
10 bits. Alors que BCD a une perte de 16/10 = 1.6, DPD a une
perte de 1024/1000 = 1.024 seulement.

Contrairement à Intel, IBM fait du décimal en hardware, d'où la
différence et les deux encodages qui ont persisté dans la norme.

[...]
Mouais. D'un autre côté, ce serait se mettre la tête dans le sable que
d'imaginer que la représentation hexadécimale des nombres flottants et
le spécificateur %a n'ont rien à voir avec le fait que la très grande
majorité des machines utilisent la base 2 (et non la base 10) pour
représenter les flottants.



De manière similaire, la fonction standard C frexp() décompose un
flottant "sous une forme binaire" (et ceci, même si l'implémentation
est décimale).

--
Vincent Lefèvre - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)
Avatar
Vincent Lefevre
Dans l'article <hpk322$13i$,
Manuel Pégourié-Gonnard écrit:

Je crois qu'on pourrait se mettre d'accord que le fait que la sens d'une
expression comme « nombre binaire » ou « nombre décimal » dépend du
contexte et relève purement d'une convention (comme un peu tout ce qui
relève du langage et des notations, en fait).



L'expression n'était même pas "nombre décimal", mais "exposant décimal".
Déjà le terme "exposant" peut prêter à confusion: les raccourcis font
qu'on peut parler de sa fonction (sémantique), de sa valeur, ou même de
son écriture (dans tel ou tel système de représentation des nombres).

--
Vincent Lefèvre - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)