Pourquoi? does.NET utiliser l'arrondi bancaire comme valeur par défaut?

selon la documentation, la méthode decimal.Round utilise un algorithme rond-à-pair qui n'est pas commun pour la plupart des applications. Donc je finis toujours par écrire une fonction personnalisée pour faire l'algorithme plus naturel rond-half-up:

public static decimal RoundHalfUp(this decimal d, int decimals)
{
    if (decimals < 0)
    {
        throw new ArgumentException("The decimals must be non-negative", 
            "decimals");
    }

    decimal multiplier = (decimal)Math.Pow(10, decimals);
    decimal number = d * multiplier;

    if (decimal.Truncate(number) < number)
    {
        number += 0.5m;
    }
    return decimal.Round(number) / multiplier;
}

est-ce que quelqu'un connaît la raison de cette décision de conception de cadre?

y a-t-il une implémentation intégrée de l'algorithme round-half-up dans le cadre? Ou peut-être une API Windows non gérée?

il pourrait être trompeur pour les débutants qui simplement écrire decimal.Round(2.5m, 0) attend 3 comme un résultat mais obtenir 2 à la place.

247
demandé sur casperOne 2008-11-22 22:51:53

5 réponses

probablement parce que c'est un meilleur algorithme. Au cours de nombreuses rondes effectuées, vous ferez la moyenne de tout cela .Les 5 finissent par s'arrondir de haut en bas. Cela donne de meilleures estimations des résultats réels si vous êtes par exemple, en ajoutant un tas de nombres arrondis. Je dirais que même si ce n'est pas ce à quoi certains peuvent s'attendre, c'est probablement la chose la plus correcte à faire.

180
répondu Kibbee 2008-11-22 19:57:14

les autres réponses avec les raisons pour lesquelles l'algorithme du Banquier (aka moitié ronde à même ) est un bon choix sont tout à fait correctes. Elle ne souffre pas d'un biais négatif ou positif autant que la méthode , à mi-chemin entre zéro et la méthode , par rapport à la plupart des distributions raisonnables.

mais la question était de savoir pourquoi. net utilise l'arrondissement actuel de Banker comme valeur par défaut - et la réponse est que Microsoft a suivi le IEEE 754 standard. Ceci est également mentionné dans MSDN pour les mathématiques.Rond dans les Remarques.

notez aussi que .NET supporte la méthode alternative spécifiée par L'IEEE en fournissant le dénombrement MidpointRounding . Ils auraient bien sûr pu fournir plus d'alternatives à la résolution des liens, mais ils ont choisi de simplement remplir la norme IEEE.

403
répondu Ostemar 2013-04-29 17:55:45

bien que je ne puisse pas répondre à la question de "pourquoi les concepteurs de Microsoft ont choisi cela comme la valeur par défaut?"Je veux juste faire remarquer qu'une fonction supplémentaire est inutile.

Math.Round vous permet de spécifier un MidpointRounding :

  • ToEven-Lorsqu'un nombre est à mi-chemin entre deux autres, il est arrondi au nombre pair le plus proche.
  • AwayFromZero-When un nombre est à mi-chemin entre deux autres, il est arrondi vers le nombre le plus proche qui est éloigné de zéro.
84
répondu Michael Stum 2011-05-31 00:04:07

décimales sont principalement utilisées pour argent ; arrondissage banquier est commun quand on travaille avec argent . Ou vous pourriez dire.

ce sont surtout les banquiers qui ont besoin type décimal; par conséquent, il ne "l'arrondi"

Banquiers arrondissement ont l'avantage qu'en moyenne, vous obtiendrez le même résultat si vous:

  • autour d'un ensemble de "les lignes de la facture" avant d'ajouter,
  • ou additionnez-les, puis additionnez le total

arrondir avant de additionner économisé beaucoup de travail dans les jours avant les ordinateurs.

(au Royaume – Uni quand nous sommes allés banques décimales ne traiterait pas avec la moitié de pence, mais pendant de nombreuses années il y avait encore une pièce de demi-pence et le magasin avait souvent des prix se terminant dans la moitié de pence-donc beaucoup d'arrondi)

23
répondu Ian Ringrose 2011-06-28 21:00:37

utilisez une autre surcharge de la fonction ronde comme ceci:

decimal.Round(2.5m, 0,MidpointRounding.AwayFromZero)

il affichera 3 . Et si vous utilisez

decimal.Round(2.5m, 0,MidpointRounding.ToEven)

vous obtiendrez l'Arrondissement de banquier.

0
répondu Omid Sadeghi 2017-03-26 14:44:22