arrondi d'un double en entier (nearbyint vs round)

Le
Isidor Ducasse
Bonjour,
Excusez si le sujet a déjà été posté, je ne l'ai pas trouvé dan=
s les
recherches.
Excusez, l'exemple est en C++, mais je pense que vous arriverez
facilement à vous y retrouvez

Voilà mon pb, je ne comprends pas nearbyint, rint, round de la lib
math
round semble convenir à mon besoin, mais qu'est-ce que c'est que cet
arrondi à l'entier impair le plus proche?
A quelle correspondance mathématique ou convention, nearbyint et rint
font-elles référence??

le code de test suivi du résultat:
<code>
#include <cstdio>
#include <cstdlib>
#include <cmath>

void testRound(double dbl)
{
double dCeil = ceil(dbl);
double dFloor = floor(dbl);
long lMano = (long) (dbl + 5e-1);
long lNear = (long) nearbyint(dbl);
long lRint = (long) rint(dbl);
long lRound = (long) round(dbl);
double diffCeil = dCeil-dbl;
double diffFloor = dbl-dFloor;
long lMano2 = (long)(
diffCeil == diffFloor ? dCeil : // explicite la convention:
si xxx.5 alors on arrondi vers ceil
diffCeil > diffFloor ? dFloor : dCeil
);

printf("| %.19f | %5.0f | %5.0f | %13.0f | %13ld | %13ld | %13ld |
%13ld | %13ld |",
dbl, dFloor, dCeil, dbl, lMano, lNear, lRint, lRound,
lMano2);
}

int main(int argc, const char** argv)
{
double dblArray[] = { 5e-1, 1.+5e-1, 2.+5e-1 }; // 0.5 1.5 2.5
int sizeA = sizeof(dblArray) / sizeof(double);

printf("| %-21s | %-5s | %-5s | %-13s | %-13s | %-13s | %-13s |
%-13s | %-13s |",
"tested value", "floor", "ceil", "print("%.0f")", "(int)(x
+0.5)", "nearbyint", "rint", "round", "ceil flr near");

for (int i = 0; i<sizeA; i++)
{
testRound( dblArray[i] );
}

return EXIT_SUCCESS;
}
</code>

<code>
| tested value | floor | ceil | print("%.0f") | (int)(x
+0.5) | nearbyint | rint | round | ceil flr near
|
| 0.5000000000000000000 | 0 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
| 1.5000000000000000000 | 1 | 2 | 2 |
2 | 2 | 2 | 2 | 2 |
| 2.5000000000000000000 | 2 | 3 | 2 |
3 | 2 | 2 | 3 | 3 |
</code>
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Antoine Leca
Le #19959301
Le 20/08/2009 11:07, Isidor Ducasse écrivit :
Voilà mon pb, je ne comprends pas nearbyint, rint, round de la lib
math



Les deux premiers sont identiques en dehors du traitement des exceptions
de résultat inexact (sujet que je ne vais pas développer, si tu ne vois
pas de quoi il retourne c'est que la différence ne t'importe pas).

round() utilise un algorithme spécifique (c'est l'algorithme que l'on
nous apprend à l'école, prendre la valeur absolue la plus grande) dans
le cas des valeurs xxx.5, indépendament des spécifications de fesetround().


round semble convenir à mon besoin, mais qu'est-ce que c'est que cet
arrondi à l'entier impair le plus proche?



Il s'agit d'un autre algorithme (souvent appelé « arrondi du banquier »,
ou plus exactement son contraire), qui à ma connaissance n'est pas
_requis_ dans une implémentation de la norme C.

L'arrondi à l'entier *pair* le plus proche (« l'arrondi du banquier »
proprement dit) est requis comme méthode par défaut par la norme IEEE754
(qui est probablement la référence utilisée par ta machine).
L'intérêt de cet algorithme par rapport à celui de round() est que les
erreurs sont statistiquement mieux réparties.


A quelle correspondance mathématique ou convention, nearbyint et rint
font-elles référence?



Suivant la valeur de fegetround():
FE_DOWNWARD comme floor()
FE_TONEAREST arrondi classique au plus proche
FE_TOWARDZERO arrondi par défaut, comme trunc(),
c'est l'effet habituel de la conversion (int)X
FE_UPWARD comme ceil()

On remarquera que (à ma connaissance) l'effet de FE_TONEAREST sur les
valeurs xxx.5 n'est pas spécifié par la norme C, on peut récupérer xxx
ou (xxx+1) suivant les implémentations; une possibilité est d'avoir
l'effet de round(), une autre serait d'arrondir vers la valeur absolue
la plus petite, on peut aussi avoir un arrondi par excès ou par défaut,
un arrondi du banquier (à l'entier pair le plus proche) ou son
contraire, voire le choix au hasard entre les deux valeurs.


le code de test suivi du résultat:



... ne concerne que ta machine.


Antoine
Isidor Ducasse
Le #19959591
merci, c'est clair.
Vincent Lefevre
Le #19961381
Dans l'article Antoine Leca
On remarquera que (à ma connaissance) l'effet de FE_TONEAREST sur les
valeurs xxx.5 n'est pas spécifié par la norme C, on peut récupérer xxx
ou (xxx+1) suivant les implémentations; une possibilité est d'avoir
l'effet de round(), une autre serait d'arrondir vers la valeur absolue
la plus petite, on peut aussi avoir un arrondi par excès ou par défaut,
un arrondi du banquier (à l'entier pair le plus proche) ou son
contraire, voire le choix au hasard entre les deux valeurs.



Cependant, si __STDC_IEC_559__ est défini, on doit avoir la règle
de l'arrondi pair, comme l'exige la norme IEC 60559 (qui reprend
l'ancienne norme IEEE 754-1985).

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)
Publicité
Poster une réponse
Anonyme