August 19, 2009

L'informatique, les nombres et les arrondis

Devinette: qu'affiche le bout de code c suivant:
double v=847.665000;
printf("v=%.2f\n",v)

Vous avez dit 847.67 ? Perdu, c'est 847.66

Tout simplement parce que:
printf("v32=%.32f\n",v);
révèle qu'en fait v vaut a peu pres: 847.66499999999996362021192908287048

Plus étonnant:

printf("%.32f\n", 1.25);
donne 1.25000000000000000000000000000000

mais printf("%.1f\n", 1.25);
donne 1.2 alors que

printf("%.32f\n", 1.75);
donne 1.75000000000000000000000000000000
et printf("%.1f\n", 1.75);
donne 1.8

Je repete: 1.25 donne 1.2 mais 1.75 donne 1.8

Etrange, non ? Et bien la c'est "tout simplement" que printf utilise non pas un arrondi arithmétique mais un arrondi "au pair le plus proche" (nommé aussi "arrondi bancaire").

Détail amusant, la fonction round() n'arrondi pas pareil, il utilise un arrondi "to nearest integer, halfway away from zero", c'est a dire que
round(1.25*10)/10 donne a peu pres 1.3 (la ou printf donnerais 1.2)
et round(1.75*10)/10 donne a peu pres 1.8

Je suis tombé des nues en voyant comment printf arrondissait: en plus de 20 ans de développement, je n'avais jamais jamais suscpecté qu'il pouvait arrondir avec une méthode différente de l'arrondi arithmétique.

Et le pire c'est que round() produit un résultat different selon le language (voir la version du language): Cf Wikipedia EN: Rounding


Références:
A Question Of Rounding
Wikipedia FR: Arrondi
Wikipedia EN: Rounding


Posted 8 years, 10 months ago on August 19, 2009
The trackback url for this post is http://mguesdon.oxymium.net/blog/bblog/trackback.php/144/

Comments have now been turned off for this post