Y at-il un moyen de faire « correct » arrondi .NET arithmétique? / C #
-
22-09-2019 - |
Question
Je suis en train de compléter un certain nombre à sa première place décimale et, compte tenu des différentes options de MidpointRounding, qui semble bien fonctionner. Un problème se pose cependant lorsque ce nombre a sunsequent décimales qui arithmétiquement affecter l'arrondissement.
Un exemple:
Avec 0.1
, 0.11..0.19
et 0.141..0.44
cela fonctionne:
Math.Round(0.1, 1) == 0.1
Math.Round(0.11, 1) == 0.1
Math.Round(0.14, 1) == 0.1
Math.Round(0.15, 1) == 0.2
Math.Round(0.141, 1) == 0.1
Mais avec 0.141..0.149
il revient toujours 0.1
, bien que 0.146..0.149
devrait arrondir à 0.2
:
Math.Round(0.145, 1, MidpointRounding.AwayFromZero) == 0.1
Math.Round(0.146, 1, MidpointRounding.AwayFromZero) == 0.1
Math.Round(0.146, 1, MidpointRounding.ToEven) == 0.1
Math.Round(0.146M, 1, MidpointRounding.ToEven) == 0.1M
Math.Round(0.146M, 1, MidpointRounding.AwayFromZero) == 0.1M
J'ai essayé de trouver une fonction qui résout ce problème, et il fonctionne bien pour ce cas, mais bien sûr, il échoue glamorously si vous essayez d'arrondir à-dire 0.144449
à son premier chiffre décimal (qui devrait être 0.2
, mais les résultats 0.1
.) (Cela ne fonctionne pas avec Math.Round () non plus.)
private double "round"(double value, int digit)
{
// basically the old "add 0.5, then truncate to integer" trick
double fix = 0.5D/( Math.Pow(10D, digit+1) )*( value >= 0 ? 1D : -1D );
double fixedValue = value + fix;
// 'truncate to integer' - shift left, round, shift right
return Math.Round(fixedValue * Math.Pow(10D, digit)) / Math.Pow(10D, digit);
}
Je suppose une solution serait d'énumérer tous les chiffres, trouver la première valeur supérieure à 4, puis arrondir, ou bien arrondir. Problème 1: Cela semble idiot, Problème 2: Je ne sais pas comment énumérer les chiffres sans gazillion de multiplications et subtractios
.Longue histoire courte: Quelle est la meilleure façon de le faire
La solution
Math.Round()
se comporte correctement.
Lorsque vous effectuez l'arrondi point médian standard, vous ne devez jamais regarder au-delà 1 chiffre décimal au-delà de l'endroit où vous arrondissez à. Si vous êtes arrondi au dixième près, alors vous ne devez jamais regarder au-delà du deuxième chiffre après la virgule.
L'idée avec arrondi milieu est que la moitié des entre-deux chiffres devraient arrondir et la moitié devraient arrondir vers le bas. Donc, pour les nombres compris entre 0,1 et 0,2, la moitié d'entre eux devrait arrondir à 0,1 et la moitié devrait arrondir à 0,2. Le point médian entre ces deux nombres est de 0,15, de sorte que le seuil est pour arrondir. 0,146 est inférieur à 0,15, donc il faut arrondir à 0,1.
Midpoint
0.10 0.15 0.20
|----------------|----|---------------------|
0.146
<---- Rounds Down
Autres conseils
Je ne comprends pas ce que vous essayez d'accomplir ici. 0,149 arrondie à la première décimale 0,1, pas 0,2
Arrondi n'est pas un processus itératif, vous arrondissez une seule fois.
0,146 arrondi à 1 chiffre décimal 0,1.
Vous ne faites pas ceci:
0.146 --> 0.15
0.15 --> 0.2
Vous faites seulement ceci:
0.146 --> 0.1
Dans le cas contraire, les éléments suivants:
0.14444444444444446
serait aussi rond à 0,2, mais il ne fonctionne pas et ne devrait pas.
Ne pas essayer de composer les «erreurs d'arrondi. Ce qui est ce que vous essayez de faire.
0,146 devrait arrondissez à .1 si vous allez à un endroit décimal.
En arrondissant à .15, puis à nouveau à 0,2 vous êtes juste d'introduire plus d'erreur d'arrondi, pas moins.