En C#, le résultat de Math.Round(2.5)
est de 2.
C'est censé être 3, n'est-ce pas ? Pourquoi est-ce 2 à la place en C# ?
En C#, le résultat de Math.Round(2.5)
est de 2.
C'est censé être 3, n'est-ce pas ? Pourquoi est-ce 2 à la place en C# ?
Tout d'abord, il ne s'agirait pas d'un bogue C# de toute façon - ce serait un bogue .NET. C# est le langage - il ne décide pas comment Math.Round
est mis en œuvre.
Et deuxièmement, non - si vous lisez les docs vous verrez que l'arrondi par défaut est "arrondi au pair" (arrondi du banquier) :
Valeur de retour
Type : System.Double
Le nombre entier le plus proche de a. Si la composante fractionnaire de a est à mi-chemin entre deux nombres entiers, dont l'un est pair et l'autre impair, le nombre pair est renvoyé est retourné. Notez que cette méthode renvoie unDouble
au lieu d'un type intégral.Remarques
Le comportement de cette méthode suit la norme IEEE 754, section 4. Ce type d'arrondi est parfois appelé arrondi au plus proche, ou arrondi au banquier. Il minimise les erreurs d'arrondi qui résultent de l'arrondissement systématique d'une valeur médiane dans une seule direction.
Vous pouvez spécifier comment Math.Round
doivent arrondir les points médians en utilisant une surcharge qui prend un MidpointRounding
valeur. Il y a une surcharge avec un MidpointRounding
correspondant à chacune des surcharges qui n'en ont pas :
Round(Decimal)
/ Round(Decimal, MidpointRounding)
Round(Double)
/ Round(Double, MidpointRounding)
Round(Decimal, Int32)
/ Round(Decimal, Int32, MidpointRounding)
Round(Double, Int32)
/ Round(Double, Int32, MidpointRounding)
Que ce défaut ait été bien choisi ou non est une autre question. ( MidpointRounding
n'a été introduite qu'en .NET 2.0. Avant cela, je ne suis pas sûr qu'il y avait un moyen facile de mettre en œuvre le comportement souhaité sans le faire soi-même). En particulier, l'histoire a montré que ce n'est pas le attendu et, dans la plupart des cas, c'est un péché capital dans la conception d'une API. Je peux voir pourquoi L'arrondi du banquier est utile... mais il reste une surprise pour beaucoup.
Vous serez peut-être intéressé de jeter un coup d'œil à l'enum équivalent Java le plus proche ( RoundingMode
) qui offre encore plus d'options. (Il ne traite pas seulement des points médians).
C'est ce qu'on appelle l'arrondi au pair (ou arrondi du banquier), qui est une stratégie d'arrondi valable pour minimiser les erreurs accumulées dans les sommes. (MidpointRounding.ToEven)
. La théorie est que, si vous arrondissez toujours un nombre de 0,5 dans la même direction, les erreurs s'accumulent plus rapidement (l'arrondi à la paire est censé minimiser cela). (a) .
Suivez ces liens pour les descriptions MSDN de :
Math.Floor
qui s'arrondit vers l'infini négatif.Math.Ceiling
qui s'arrondit vers l'infini positif.Math.Truncate
qui arrondit vers le haut ou le bas vers zéro.Math.Round
qui arrondit au nombre entier le plus proche ou au nombre de décimales spécifié. Vous pouvez spécifier le comportement s'il est exactement équidistant entre deux possibilités, comme l'arrondi pour que le dernier chiffre soit pair (" Round(2.5,MidpointRounding.ToEven)
" devenant 2) ou de façon à ce qu'il soit plus éloigné de zéro (" Round(2.5,MidpointRounding.AwayFromZero)
" devenir 3).Le diagramme et le tableau suivants peuvent vous aider :
-3 -2 -1 0 1 2
+--|------+---------+----|----+--|------+----|--|-+
a b c d e
a=-2.7 b=-0.5 c=0.3 d=1.5 e=2.8
====== ====== ===== ===== =====
Floor -3 -1 0 1 2
Ceiling -2 0 1 2 3
Truncate -2 0 0 1 2
Round(ToEven) -3 0 0 2 3
Round(AwayFromZero) -3 -1 0 2 3
Notez que Round
est beaucoup plus puissant qu'il n'y paraît, simplement parce qu'il peut arrondir à un nombre spécifique de décimales. Tous les autres arrondissent toujours à zéro décimale. Par exemple :
n = 3.145;
a = System.Math.Round (n, 2, MidpointRounding.ToEven); // 3.14
b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15
Avec les autres fonctions, vous devez utiliser la technique de multiplication/division pour obtenir le même effet :
c = System.Math.Truncate (n * 100) / 100; // 3.14
d = System.Math.Ceiling (n * 100) / 100; // 3.15
(a) Bien entendu, cette théorie dépend du fait que vos données présentent une répartition assez égale des valeurs entre les moitiés paires (0,5, 2,5, 4,5, ...) et impaires (1,5, 3,5, ...).
Si tous les "demi-valeurs" sont des pairs (par exemple), les erreurs s'accumuleront aussi vite que si vous arrondissiez toujours au chiffre supérieur.
Desde MSDN, Math.Round(double a) retours :
Le nombre entier le plus proche de a. Si la composante fractionnaire de a est à mi-chemin entre deux nombres entiers, dont l'un est pair et l'autre impair, le nombre pair est renvoyé est renvoyé.
... et donc 2,5, se situant à mi-chemin entre 2 et 3, est arrondi au nombre pair (2) inférieur. Arrondissement du banquier (ou round-to-even), et est une norme d'arrondi couramment utilisée.
Même article de MSDN :
Le comportement de cette méthode suit Norme IEEE 754, section 4. Ce type d'arrondi type d'arrondi est parfois appelé arrondi au plus proche, ou arrondi du banquier arrondir. Il minimise les erreurs d'arrondi qui résultent du fait d'arrondir systématiquement une valeur intermédiaire dans une seule direction.
Vous pouvez spécifier un comportement d'arrondi différent en appelant les surcharges de Math.Round qui prennent une valeur de MidpointRounding
mode.
Vous devriez consulter MSDN pour Math.Round
:
Le comportement de cette méthode suit la norme IEEE 754, section 4. Ce type d'arrondi est parfois appelé arrondi au plus proche, ou arrondi du banquier.
Vous pouvez spécifier le comportement de Math.Round
en utilisant une surcharge :
Math.Round(2.5, 0, MidpointRounding.AwayFromZero); // gives 3
Math.Round(2.5, 0, MidpointRounding.ToEven); // gives 2
Considérez la tâche d'arrondir un nombre qui contient une fraction à, disons, un nombre entier. Dans ce cas, le processus d'arrondi consiste à déterminer quel nombre entier représente le mieux le nombre que vous arrondissez.
Dans l'arrondi commun, ou "arithmétique", il est clair que 2.1, 2.2, 2.3 et 2.4 s'arrondissent à 2.0 ; et 2.6, 2.7, 2.8 et 2.9 à 3.0.
Il reste donc 2.5, qui n'est pas plus proche de 2.0 que de 3.0. C'est à vous de choisir entre 2.0 et 3.0, l'un ou l'autre serait tout aussi valable.
Pour les nombres négatifs, -2,1, -2,2, -2,3 et -2,4 deviendraient -2,0 ; et -2,6, 2,7, 2,8 et 2,9 deviendraient -3,0 avec l'arrondi arithmétique.
Pour -2,5, il faut choisir entre -2,0 et -3,0.
Autres formes d'arrondis
L'arrondi à l'unité supérieure prend n'importe quel nombre avec des décimales et en fait le nombre "entier" suivant. Ainsi, non seulement 2,5 et 2,6 sont arrondis à 3,0, mais 2,1 et 2,2 le sont également.
L'arrondi à l'unité supérieure éloigne les nombres positifs et négatifs du zéro. Par exemple, 2,5 à 3,0 et -2,5 à -3,0.
L'arrondi à l'unité inférieure tronque les nombres en supprimant les chiffres non désirés. Cela a pour effet de rapprocher les nombres de zéro. Par exemple, 2,5 à 2,0 et -2,5 à -2,0.
Dans l'"arrondi du banquier" - dans sa forme la plus courante - le 0,5 à arrondir est arrondi soit vers le haut, soit vers le bas, de sorte que le résultat de l'arrondi soit toujours un nombre pair. Ainsi, 2,5 s'arrondit à 2,0, 3,5 à 4,0, 4,5 à 4,0, 5,5 à 6,0, et ainsi de suite.
L'option "arrondi alterné" alterne le processus pour tout .5 entre l'arrondi inférieur et l'arrondi supérieur.
L'"arrondi aléatoire" arrondit un 0,5 vers le haut ou vers le bas de manière totalement aléatoire.
Symétrie et asymétrie
Une fonction d'arrondi est dite "symétrique" si elle arrondit tous les nombres à l'écart de zéro ou arrondit tous les nombres vers zéro.
Une fonction est " asymétrique " si elle arrondit les nombres positifs vers zéro et les nombres négatifs à partir de zéro. Par exemple, 2,5 à 2,0 ; et -2,5 à -3,0.
L'asymétrie est également une fonction qui arrondit les nombres positifs à l'écart de zéro et les nombres négatifs vers zéro. Par exemple, 2,5 à 3,0 ; et -2,5 à -2,0.
La plupart du temps, les gens pensent à un arrondi symétrique, où -2,5 sera arrondi à -3,0 et 3,5 sera arrondi à 4,0. (en C# Round(AwayFromZero)
)
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.