Pourquoi les Mathématiques.Round(2.5) retour 2 au lieu de 3?
En C#, le résultat de Math.Round(2.5)
est 2.
Il est censé être 3, n'est-ce pas? Pourquoi est-il 2 plutôt en C#?
C'est en fait une fonctionnalité. Voir <a href="" >msdn.microsoft.com/en-us/library/... la documentation MSDN</a>. Ce genre de arrondissement est connu comme l'arrondi. Comme pour une solution de contournement, il est <a href="" >msdn.microsoft.com/en-us/library/... la surcharge</a> qui permet à l'appelant de spécifier la façon de faire les arrondis.
Apparemment, le tour de méthode, lorsqu'on a demandé à arrondir un nombre exactement entre deux entiers, renvoie le nombre entier pair. Ainsi, Les Maths.Round(3.5) renvoie 4. Voir cet article
SQL Server tours de cette façon; les résultats de l'épreuve intéressants quand il y a un C# test de l'unité ti valider l'arrondissement fait en T-SQL.
ce n'est pas un bug. C'est la façon variable binaire points.
Apparemment, le tour de méthode, lorsqu'on a demandé à arrondir un nombre exactement entre deux entiers, renvoie le nombre entier pair. Ainsi, Les Maths.Round(3.5) renvoie 4. Voir cet article
Math.Round(2.5, 0, MidpointRounding.AwayFromZero);
SQL Server tours de cette façon; les résultats de l'épreuve intéressants quand il y a un C# test de l'unité ti valider l'arrondissement fait en T-SQL.
ce n'est pas un bug. C'est la façon variable binaire points.
1.005
ne peuvent pas être représentés exactement en double. C'est probablement 1.00499...
. Si vous utilisez Decimal
ce problème disparaîtra. L'existence des Mathématiques.Tour de surcharge qui prend un certain nombre de chiffres après la virgule sur le double est douteuse choix de conception de l'OMI, depuis qu'il est rarement travaillent dans une manière significative.OriginalL'auteur jeffu | 2009-06-10
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, ce ne serait pas un C# bug de toute façon, il serait une .NET bug. C# est le langage - ce n'est pas de décider de la façon dont
Math.Round
est mis en œuvre.Et d'autre part, aucun - si vous lisez les docs, vous verrez que l'arrondi par défaut est "rond de même" (l'arrondi):
Vous pouvez spécifier comment
Math.Round
devrait ronde mi-points à l'aide de une surcharge qui prend unMidpointRounding
valeur. Il y a une surcharge avec unMidpointRounding
correspondant à chacune des surcharges qui n'en a pas:Round(Décimal)
/Round(Décimal, MidpointRounding)
Round(Double)
/Round(Double, MidpointRounding)
Round(Décimal, Int32)
/Round(Décimal, Int32, MidpointRounding)
Round(Double, Int32)
/Round(Double, Int32, MidpointRounding)
Si ce défaut a été bien choisi ou non est une autre affaire. (
MidpointRounding
a été introduit 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 désiré sans le faire vous-même.) En particulier, l'histoire a montré que ce n'est pas le devrait comportement - et dans la plupart des cas, c'est un péché cardinal de l'API de dessin. Je peux voir pourquoi l'Arrondi est utile... mais c'est toujours une surprise pour beaucoup.Vous pouvez être intéressé à regarder le plus proche de Java équivalent enum (
RoundingMode
), ce qui offre encore plus d'options. (Il n'est pas seulement affaire avec les milieux.)Je me souviens de ce problème dans visual basic à l'avant .NET obtenu appliquée.
permettez-moi d'ajouter que l'arrondi au plus proche même est une partie de la virgule flottante standard?
En effet, la Norme IEEE 754, l'article 4 que les états de documentation.
+1 pour le "ce n'est pas le comportement attendu [...] c'est un péché cardinal dans la conception d'API"
OriginalL'auteur
Qui est appelé l'arrondissement de même (ou de l'arrondi), qui est valide arrondissement stratégie pour réduire les charges des erreurs dans les montants
(MidpointRounding.ToEven)
. La théorie est que, si vous avez toujours autour de 0,5 nombre dans le même sens, les erreurs s'accumulent plus vite (tour-de-même est censé limiter l') a.Suivez ces liens pour la MSDN descriptions de:
Math.Étage
, qui arrondit vers l'infini négatif.Math.Plafond
, qui arrondit vers l'infini positif.Math.Tronquer
, qui arrondit vers le haut ou vers le bas vers zéro.Math.Ronde
, qui arrondit à l'entier le plus proche ou le nombre de décimales spécifié. Vous pouvez spécifier le comportement si c'est exactement à égale distance entre les deux possibilités, telles que l'arrondi de sorte que le dernier chiffre est le même ("Round(2.5,MidpointRounding.ToEven)
" devenir 2) ou qu'il soit le plus loin possible à partir de zéro ("Round(2.5,MidpointRounding.AwayFromZero)
" devenir 3).Le diagramme suivant et le tableau peut aider:
Noter que
Round
est beaucoup plus puissant que ce qu'il semble, tout simplement parce qu'il peut arrondir à un nombre de décimales. Tous les autres tour à zéro décimales toujours. Par exemple:Avec les autres fonctions, vous devez utiliser multiplier/diviser la ruse pour obtenir le même effet:
a bien sûr, cette théorie repose sur le fait que vos données ont une assez même la propagation de valeurs dans le même moitiés (0.5, 2.5, 4.5, ...) et de l'impair moitiés (1.5, 3.5, ...).
Si tous la "demi-valeurs" sont evens (par exemple), les erreurs s'accumulent tout aussi rapide que si vous avez toujours arrondi.
+2 très bonne explication
Bonne explication! Je voulais voir par moi-même comment l'erreur s'accumule et j'ai écrit un script qui montre que les valeurs arrondies à l'aide de l'arrondi, à long terme, ont leurs sommes et des moyennes beaucoup plus proche de ces valeurs d'origine. github.com/AmadeusW/RoundingDemo photos de parcelles disponibles)
Peu de temps après: ne devrait pas
e
tique (= 2.8), droit de2
tique?bonne prise, fixé maintenant.
OriginalL'auteur
De MSDN, les Maths.Round(double) retourne:
... et donc 2,5, étant à mi-chemin entre 2 et 3, est arrondi au nombre pair (2). ceci est appelé L'Arrondi (ou tour-de-même), et est couramment utilisé arrondi standard.
Même article MSDN:
Vous pouvez spécifier un autre arrondissement comportement en appelant les surcharges de Mathématiques.Autour de prendre un
MidpointRounding
mode.OriginalL'auteur
Vous devriez vérifier MSDN pour
Math.Ronde
:Vous pouvez spécifier le comportement de
Math.Round
à l'aide d'une surcharge:OriginalL'auteur
La nature de l'arrondissement
Considérer la tâche de l'arrondi d'un nombre qui contient une fraction, par exemple, un nombre entier. Le processus de l'arrondissement dans ce cas, c'est de déterminer le nombre entier qui représente le mieux le nombre vous d'arrondi.
En commun, ou "arithmétique" de l'arrondissement, il est clair que, 2.1, 2.2, 2.3 et 2.4 tour à 2.0 et 2.6, 2.7, 2.8 et 2.9 3.0.
Que les feuilles de 2,5, ce qui est loin d'être à la 2.0 que c'est à la version 3.0. C'est à vous de choisir entre 2.0 et 3.0, serait tout aussi valable.
Pour moins numéros, -2.1, -2.2, -2.3 et -2.4, deviendrait -2.0; et -2.6, 2.7, 2.8 et 2.9 deviendrait -3.0 en vertu de l'arrondi arithmétique.
Pour -2.5 un choix est nécessaire entre -2.0 et -3.0.
D'autres formes de l'arrondissement
'Arrondi' prend un nombre avec décimales et en fait le suivant 'ensemble de l' nombre. Ainsi, non seulement 2.5 et 2.6 tour à 3.0, mais il ne faut 2.1 et 2.2.
Arrondissement se déplace à la fois positifs et les nombres négatifs, loin de zéro. Par exemple. De 2.5 à 3.0 et -2.5 à -3.0.
'Arrondi vers le bas" tronque les numéros de débitage hors les chiffres. Cela a pour effet de déplacer les numéros de vers zéro. Par exemple. 2.5 2.0 et -2.5 à -2.0
Dans "l'arrondi" - dans sa forme la plus courante - l'.5 être arrondi est arrondi vers le haut ou vers le bas de sorte que le résultat de l'arrondi est toujours un nombre pair. Ainsi, à 2,5 tours à 2.0, 3.5 et 4.0, 4.5 4.0, 5.5 à 6.0, et ainsi de suite.
'Autre arrondi' alterne le processus pour tout .5 entre l'arrondi vers le bas et arrondi vers le haut.
L'arrondissement aléatoire des tours d'une .5 vers le haut ou vers le bas de façon totalement aléatoire.
La symétrie et l'asymétrie
Un arrondissement la fonction est dite "symétrique" si elle arrondit tous les numéros de loin à partir de zéro ou de tours tous les numéros de vers zéro.
Une fonction est "asymétriques" si les tours des nombres positifs vers zéro et les nombres négatifs à l'écart à partir de zéro.. par exemple. De 2,5 à 2,0; et -2.5 à -3.0.
Également asymétrique est une fonction qui arrondit les nombres positifs, loin de zéro et les nombres négatifs vers zéro. Par exemple. De 2.5 à 3.0; et -2.5 à -2.0.
La plupart du temps les gens pensent d'arrondi symétrique, où -2.5 sera arrondi vers -3.0 et 3,5 sera arrondi vers 4.0. (en C#
Round(AwayFromZero)
)OriginalL'auteur
La valeur par défaut
MidpointRounding.ToEven
, ou des Banquiers d'arrondi (2.5 devenir 2, 4.5 devient 4 et ainsi de suite) a m'a piqué avant avec la rédaction de rapports pour la comptabilité, donc je vais écrire quelques mots de ce que j'ai trouvé, précédemment et de la recherche pour ce poste.Qui sont ces banquiers qui sont arrondis vers le bas sur le même nombre (British bankers, peut-être!)?
De wikipedia
Il semble que d'une manière très étrange de l'arrondissement en particulier pour des opérations bancaires, à moins bien sûr que les banques utilisent pour recevoir beaucoup de dépôts de même montant. Dépôt de € 2,4 m, mais nous allons l'appeler £2m sir.
La Norme IEEE 754 remonte à 1985 et donne à la fois des moyens de d'arrondissement, mais avec du banquier comme recommandé par la norme. Cette article de wikipedia a une longue liste de langues de mettre en œuvre l'arrondissement (corrigez-moi si l'un des ci-dessous sont fausses) et la plupart n'utilisent pas des Banquiers mais la arrondissement on vous apprend à l'école:
OriginalL'auteur
À partir de MSDN:
http://msdn.microsoft.com/en-us/library/system.math.round.aspx
OriginalL'auteur
Depuis Silverlight ne prend pas en charge la MidpointRounding option, vous devez écrire votre propre. Quelque chose comme:
Pour les exemples, y compris la façon de l'utiliser comme une extension de voir le post: .NET et Silverlight Arrondissement
OriginalL'auteur
J'ai eu ce problème où mon serveur SQL tours jusqu'à 0,5 à 1 alors que mon application C# n'a pas. Donc, vous voyez deux résultats différents.
Voici une implémentation de l'int/long. C'est la façon dont Java tours.
C'est probablement la méthode la plus efficace que vous pourriez penser ainsi.
Si vous voulez garder un lit double et d'utilisation, la précision décimale , puis c'est vraiment juste une question de l'utilisation des exposants de 10, basé sur le nombre de décimales.
Vous pouvez entrer un négatif virgule pour les décimales et c'est fin mot.
OriginalL'auteur
Ce post a la réponse que vous cherchez:
http://weblogs.asp.net/sfurman/archive/2003/03/07/3537.aspx
Fondamentalement, c'est ce qu'il dit:
Valeur De Retour
Le nombre le plus proche de la valeur avec précision égale aux chiffres. Si la valeur est à mi-chemin entre les deux nombres, dont l'un est pair et l'autre impair, le même nombre est retourné. Si la précision de la valeur est de moins de chiffres, alors la valeur est retourné à l'identique.
Le comportement de cette méthode suit la Norme IEEE 754, section 4. Ce type d'arrondi est parfois appelé d'arrondi au plus près, ou de l'arrondi. Si les chiffres est égale à zéro, ce type d'arrondi est parfois appelé arrondi vers zéro.
OriginalL'auteur
Silverlight ne prend pas en charge la MidpointRounding option.
Voici une méthode d'extension pour Silverlight qui ajoute de la MidpointRounding enum:
Source: http://anderly.com/2009/08/08/silverlight-midpoint-rounding-solution/
OriginalL'auteur
à l'aide d'un personnalisé arrondi
>.5
produit le même comportement queMath.Round
. La question est de whas se produit lorsque la partie décimale est exactement0.5
. Les mathématiques.Tour vous permet de spécifier le type de l'arrondissement de l'algorithme que vous voulezOriginalL'auteur
Moyen Simple est:
OriginalL'auteur
Voici la façon dont j'ai eu à travailler autour de :
Essayer avec 1.905 avec 2 décimales donnera 1.91 comme prévu, mais
Math.Round(1.905,2,MidpointRounding.AwayFromZero)
donne 1.90! Les mathématiques.Tour méthode est absolument incohérent et inutilisable pour la plupart des notions de base des problèmes de programmeurs peuvent rencontrer. Je dois vérifier si(int) 1.905 * decimalPowerOfTen = Math.Round(number * decimalPowerOfTen, 2)
car je ne veux pas rond jusqu'à ce que doit être arrondi à l'inférieur.Math.Round(1.905,2,MidpointRounding.AwayFromZero)
retourne1.91
OriginalL'auteur
C'est laid comme tout l'enfer, mais produit toujours correct arrondi arithmétique.
Math.Round
et de préciser la façon dont vous le souhaitez arrondir.OriginalL'auteur