OVH Cloud OVH Cloud

Problème d'arrondi sur la multiplication

5 réponses
Avatar
Sébastien Curutchet
Bonjour,

Voici mon code :

double a = 150.0;
double b = 0.57;
b*=a;

Regarder avec l'espion express le contenu de b, et au lieu d'être 85.5 j'ai
85.499999...

Est ce uniquement chez moi ou avez vous le même problème ?


Pour information :
PIV 1.7Ghz
Win XP SP1
Framework 1.1 SP1

D'avance merci.

Sébastien Curutchet

5 réponses

Avatar
Eric Vernié [MS]
Bonjour Sébastien,

Utilise à la place des decimal comme ceci
decimal a = 150.0M;
decimal b = 0.57M;
b*=a;

Dans le framework .NET les doubles (et comme dans beaucoup de langages et
autres plates-formes) utilisent la norme IEC 60589:1989 (IEEE 754)
En gros, quel pourrait etre le codage en binaire de 0,00000001. 1 ou 0 ? on
ne sait pas bien representer le cas, alors on utilise des artifices tel que
cette norme, pour dire, qu'un double sera codé en interne sur 2 octets avec
un bit de signature 8 bits d'exposant et 23 de Mantisse......un algorithme
au milieu et le tour est joué.
Tout ce jolie petit monde donne la representation d'un double (ou d'un
single) avec une précision qui donne le résultat que tu as obtenus.

Un coup de google sur IEEE 754 et tu auras l'algo exacte sur cette norme.

A+

Eric Vernié
Microsoft France

"Sébastien Curutchet" a écrit dans le message
de news: uh%
Bonjour,

Voici mon code :

double a = 150.0;
double b = 0.57;
b*=a;

Regarder avec l'espion express le contenu de b, et au lieu d'être 85.5
j'ai
85.499999...

Est ce uniquement chez moi ou avez vous le même problème ?


Pour information :
PIV 1.7Ghz
Win XP SP1
Framework 1.1 SP1

D'avance merci.

Sébastien Curutchet




Avatar
Zazar
Bonjour, je corrige juste une petite erreur d'étourderie.

double sera codé en interne sur 2 octets avec
un bit de signature 8 bits d'exposant et 23 de Mantisse......



Ca c'est la représentation d'un float (en rajoutant le bit de signe), celle
d'un double tient sur 64 bits (1 pour le signe, 52 pour la mantisse et 11
pour l'exposant).

--
Zazar
Avatar
Sébastien Curutchet
Merci.

L'histoire de l'algorithme avec la mantisse je connaissais, mais c'est la
première fois que je tombe sur ce problème, à croire que j'ai eu de la
chance.

En tout cas merci pour vos explications.

Cordialement,

Sébastien Curutchet

"Eric Vernié [MS]" a écrit dans le message de
news:%
Bonjour Sébastien,

Utilise à la place des decimal comme ceci
decimal a = 150.0M;
decimal b = 0.57M;
b*=a;

Dans le framework .NET les doubles (et comme dans beaucoup de langages et
autres plates-formes) utilisent la norme IEC 60589:1989 (IEEE 754)
En gros, quel pourrait etre le codage en binaire de 0,00000001. 1 ou 0 ?


on
ne sait pas bien representer le cas, alors on utilise des artifices tel


que
cette norme, pour dire, qu'un double sera codé en interne sur 2 octets


avec
un bit de signature 8 bits d'exposant et 23 de Mantisse......un algorithme
au milieu et le tour est joué.
Tout ce jolie petit monde donne la representation d'un double (ou d'un
single) avec une précision qui donne le résultat que tu as obtenus.

Un coup de google sur IEEE 754 et tu auras l'algo exacte sur cette norme.

A+

Eric Vernié
Microsoft France

"Sébastien Curutchet" a écrit dans le


message
de news: uh%
> Bonjour,
>
> Voici mon code :
>
> double a = 150.0;
> double b = 0.57;
> b*=a;
>
> Regarder avec l'espion express le contenu de b, et au lieu d'être 85.5
> j'ai
> 85.499999...
>
> Est ce uniquement chez moi ou avez vous le même problème ?
>
>
> Pour information :
> PIV 1.7Ghz
> Win XP SP1
> Framework 1.1 SP1
>
> D'avance merci.
>
> Sébastien Curutchet
>
>




Avatar
Bruno Jouhier [MVP]
Quelques précisions:

un double est codé sur 8 octets, pas 2. Un float est codé sur 4 octets.

Il n'y a pas vraiment d'algorithme au milieu, on approxime le nombre par un
nombre de la forme s m* 2^e (appelé fraction binaire) où s est le signe
(codé sur 1 bit), m est la mantisse (sur 52 bits) et e l'exposant (sur 11
bits), soit 64 bits en tout.

Le problème c'est que la plupart des nombres décimaux (les nombres de la
forme i * 10^j, avec i,j entiers relatifs) ne sont pas représentables
*exactement* sous forme de fraction binaire. Par exemple, un nombre aussi
simple que 0.1 n'est pas représentable exactement par une fraction binaire
(il y aurait une infinité de chiffres binaires (bits) après la virgule). En
revanche 0.5 et 0.125 sont exactement représentables. Dès qu'on manipule un
nombre comme 0.1 en type double, on est à la merci d'erreurs de calcul car
on manipule une représentation approchée.

En revanche le type "décimal" représente les nombres sous la forme i * 10^-j
(où i est un entier signé sur 96 bits et j un entier de 0 à 28). Il
représente donc exactement les nombres décimaux ayant jusqu'à 28/29
chiffres, dans un domaine de valeurs très large. Si tu fais les calculs en
"décimal", tu manipules des représentations *exactes* de tes nombres, et tu
évites les pièges du type double.

Bruno.


"Sébastien Curutchet" a écrit dans le message
de news:
Merci.

L'histoire de l'algorithme avec la mantisse je connaissais, mais c'est la
première fois que je tombe sur ce problème, à croire que j'ai eu de la
chance.

En tout cas merci pour vos explications.

Cordialement,

Sébastien Curutchet

"Eric Vernié [MS]" a écrit dans le message de
news:%
Bonjour Sébastien,

Utilise à la place des decimal comme ceci
decimal a = 150.0M;
decimal b = 0.57M;
b*=a;

Dans le framework .NET les doubles (et comme dans beaucoup de langages et
autres plates-formes) utilisent la norme IEC 60589:1989 (IEEE 754)
En gros, quel pourrait etre le codage en binaire de 0,00000001. 1 ou 0 ?


on
ne sait pas bien representer le cas, alors on utilise des artifices tel


que
cette norme, pour dire, qu'un double sera codé en interne sur 2 octets


avec
un bit de signature 8 bits d'exposant et 23 de Mantisse......un
algorithme
au milieu et le tour est joué.
Tout ce jolie petit monde donne la representation d'un double (ou d'un
single) avec une précision qui donne le résultat que tu as obtenus.

Un coup de google sur IEEE 754 et tu auras l'algo exacte sur cette norme.

A+

Eric Vernié
Microsoft France

"Sébastien Curutchet" a écrit dans le


message
de news: uh%
> Bonjour,
>
> Voici mon code :
>
> double a = 150.0;
> double b = 0.57;
> b*=a;
>
> Regarder avec l'espion express le contenu de b, et au lieu d'être 85.5
> j'ai
> 85.499999...
>
> Est ce uniquement chez moi ou avez vous le même problème ?
>
>
> Pour information :
> PIV 1.7Ghz
> Win XP SP1
> Framework 1.1 SP1
>
> D'avance merci.
>
> Sébastien Curutchet
>
>








Avatar
Eric Vernié [MS]
oups ;-)

EV


"Zazar" a écrit dans le message
de news:
Bonjour, je corrige juste une petite erreur d'étourderie.

double sera codé en interne sur 2 octets avec
un bit de signature 8 bits d'exposant et 23 de Mantisse......



Ca c'est la représentation d'un float (en rajoutant le bit de signe),
celle
d'un double tient sur 64 bits (1 pour le signe, 52 pour la mantisse et 11
pour l'exposant).

--
Zazar