Question

Selon la documentation, le decimal.Round La méthode utilise un algorithme d'arrondi 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 de demi-tour:

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;
}

Quelqu'un connaît-il la raison de cette décision de conception de cadre?

Existe-t-il une implémentation intégrée de l'algorithme d'arrondi dans le framework? Ou peut-être une API Windows non gérée?

Il peut être trompeur pour les débutants d'écrire simplement decimal.Round (2.5m, 0) en prévoyant 3 mais en obtenant 2 à la place.

Était-ce utile?

La solution

Probablement parce que c'est un meilleur algorithme. Au cours des nombreux arrondis effectués, vous constaterez que tous les 0,5 sont arrondis de la même manière. Cela donne de meilleures estimations des résultats réels si vous ajoutez, par exemple, un ensemble 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.

Autres conseils

Les autres réponses expliquent pourquoi l'algorithme de Banker (alias arrondit la moitié à la même ) est un bon choix sont tout à fait correct. Il ne souffre pas de biais négatif ou positif autant que la méthode à mi-chemin de zéro sur la plupart des distributions raisonnables.

Mais la question était de savoir pourquoi .NET utilisait l'arrondi réel de Banker comme valeur par défaut - et la réponse était que Microsoft avait suivi la IEEE 754 standard. Ceci est également mentionné dans MSDN pour Math.Round sous Remarques.

Notez également que .NET prend en charge la méthode alternative spécifiée par IEEE en fournissant l'énumération MidpointRounding . Ils auraient bien sûr pu fournir davantage d'alternatives à la résolution de liens, mais ils choisissent simplement conforme à la norme IEEE.

Bien que je ne puisse pas répondre à la question "Pourquoi les concepteurs de Microsoft ont-ils choisi cette option par défaut?", je tiens simplement à souligner qu'une fonction supplémentaire est inutile.

Math.Round a> 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 - Lorsqu'un nombre est à mi-chemin entre deux autres, il est arrondi au nombre le plus proche qui est loin de zéro.

Les décimales sont principalement utilisées pour l'argent ; L’arrondissement du banquier est courant lorsqu’on travaille avec argent . Ou vous pourriez dire.

  

Ce sont surtout les banquiers qui ont besoin de   type décimal; donc il fait   Arrondi de & # 8220; banquier & <8221;

L’arrondissement des banquiers a l’avantage que vous obtiendrez en moyenne le même résultat si:

  • arrondissez un ensemble de & # 8220; lignes de facturation & # 8221; avant de les additionner,
  • ou additionnez-les puis arrondissez le total

Arrondir avant d’ajouter beaucoup de travail économisé au cours des jours précédant les ordinateurs.

(Au Royaume-Uni, lorsque nous sommes allés en décimales, les banques décimales ne traitaient pas le demi-centime, mais pendant de nombreuses années, il restait une pièce de un demi-centime et les prix des magasins se terminaient souvent par un demi-centime.

Utilisez une autre surcharge de la fonction Round comme ceci:

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

Le résultat sera 3 . Et si vous utilisez

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

vous obtiendrez l'arrondissement du banquier.

Notez également que " arrondir " via une chaîne de formatage (comme "0") produit un résultat différent de celui de "Math.Round ()". À savoir que 5, .5, etc. sont toujours arrondis:

let d, d' = 2.5, 3.5

Debug.WriteLine(Math.Round(d))      // 2.5 -> 2
Debug.WriteLine(d.ToString("0"))    // 2.5 -> 3

Debug.WriteLine(Math.Round(d'))     // 3.5 -> 4
Debug.WriteLine(d'.ToString("0"))   // 3.5 -> 4


let dd, dd' = 2.25, 2.35

Debug.WriteLine(Math.Round(dd, 1))     // 2.25 -> 2.2
Debug.WriteLine(dd.ToString("0.0"))    // 2.25 -> 2.3

Debug.WriteLine(Math.Round(dd', 1))    // 2.35 -> 2.4
Debug.WriteLine(dd'.ToString("0.0"))   // 2.35 -> 2.4
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top