Besoin d'aide arrondir à 2 décimales

Pourquoi est-ce que c'est quand je fais ce qui suit...

Math.Round(0.75, 1, MidpointRounding.AwayFromZero)

je 0.8

mais quand je fais la suite...

Math.Round(0.575, 2, MidpointRounding.AwayFromZero)

Je ne comprends pas 0.58. Au lieu de cela je obtenir de 0,57. Je veux tout ce qui est à 5 et plus, donc 0,575 devrait être 0,58.

18
demandé sur w͏̢in̡͢g͘̕ed̨p̢͟a͞n͏͏t̡͜͝he̸r̴ 2012-08-24 20:18:39

3 réponses

le problème sera que vous ne pouvez pas représenter 0.575 exactement comme un nombre flottant binaire (par exemple un double). Bien que je ne sais pas exactement il semble que la représentation la plus proche est probablement juste un peu plus bas et donc en arrondissant il utilise la représentation vraie et arrondit vers le bas.

si vous voulez éviter ce problème, utilisez un type de données plus approprié. decimal faire ce que vous souhaitez:

Math.Round(0.575M, 2, MidpointRounding.AwayFromZero)

Résultat: 0.58

la raison pour laquelle la bonne chose est qu'il est facile à représenter en virgule flottante binaire puisqu'il est simple 1/2 + 1/4 (ie 2^-1 +2^-2). En général n'importe quelle somme finie des puissances de deux peut être représentée en point flottant binaire. Les Exceptions sont quand vos pouvoirs de 2 portée trop grande une gamme (par exemple 2^100+2 n'est pas exactement représentatif).

Modifier pour ajouter:

formatage doubles pour la sortie en C# pourrait être intéressant en termes de comprendre pourquoi il est si difficile de comprendre que 0,575 est pas vraiment de 0,575. Le DoubleConverter dans la réponse acceptée montrera que 0.575 comme une chaîne exacte est 0.5749999999999999555910790149937383830547332763671875 vous pouvez voir à partir de cela pourquoi l'arrondissement donne 0.57.

32
répondu Chris 2017-05-23 12:00:31

System.Math.Round la méthode utilise le Double structure, qui, comme d'autres l'ont fait remarquer, est sujette à des erreurs de précision en virgule flottante. La solution simple I trouvé à ce problème lorsque j'ai rencontré, c'était d'utiliser le System.Decimal.Round méthode, qui ne souffre pas du même problème et ne nécessite pas de rediffusion de vos variables en décimales:

Decimal.Round(0.575, 2, MidpointRounding.AwayFromZero)

Résultat: 0.58

9
répondu Antagony 2012-08-24 17:09:12

il est causé par un manque de précision avec doubles / décimales (i.e. - la fonction ne sera pas toujours donner le résultat que vous attendez).

Voir le lien suivant: MSDN en maths.Ronde

Voici la citation:

en raison de la perte de précision qui peut résulter de la représentation des valeurs décimales comme des nombres à virgule flottante ou d'effectuer des opérations arithmétiques sur les valeurs à virgule flottante, dans certains cas, le La méthode Ronde(Double, Int32, MidpointRounding) peut ne pas sembler arrondir les valeurs médianes spécifiées par le paramètre mode.Ceci est illustré dans l'exemple suivant, où 2.135 est arrondi à 2.13 au lieu de 2,14.Cela se produit parce que la méthode multiplie la valeur à l'interne par 10digits, et l'opération de multiplication dans ce cas souffre d'une perte de précision.

2
répondu Jason Hermann 2012-08-24 16:36:49