49 votes

Comment comparer correctement les valeurs décimales en C #?

Je viens d'un milieu en C++, et je sais que vous ne pouvez pas comparer avec précision les flotteurs pour l'égalité. Pour le C#, j'ai simplement supposé la même politique s'applique à des valeurs décimales, ou toute valeur à virgule flottante en général.

En gros, j'ai deux valeurs décimales et si elles ne sont PAS égaux les uns aux autres, j'ai besoin d'effectuer une action. par exemple:

decimal value1, value2;
// Assume value1 and value2 are set somewhere to valid values.
if( value1 != value2 )
{
    // Do something
}

Si cela ne fonctionne pas comme prévu, je suis prêt à accepter une solution qui répond à une comparaison d'égalité avec une marge d'erreur, dire comme .00001 ou quelque chose comme ça. Quelle serait la solution recommandée pour ce problème?

32voto

fretje Points 6074

Votre code fonctionne comme prévu. C# decimals sont optimisés pour être très précis à la représentation en base 10 des nombres, donc si c'est ce que vous êtes en comparant (argent, ...), tout devrait bien se passer.

Voici un très explication claire quant à la précision des décimales par Jon Skeet:

Quelle est la différence entre Décimal, Float et Double en C#?

7voto

Mark Points 7136

Les décimales sont des chiffres exacts, vous pouvez utiliser == ou! = Pour tester l'égalité.

Je suppose que je devrais faire attention à dire que cela dépend de la nature des données et du type d'opérations que vous effectuez avec lesquelles.

Par exemple:

 .1d + .2d == 0.3d // false
.1f + .2f == 0.3f // false
.1m + .2m == 0.3m // true
 

5voto

Kim Points 456

J'enquêtais sur quelque chose de similaire, mais avec une précision au lieu d'une marge d'erreur et j'ai fini par écrire des extensions pour Float. Cependant, cela peut facilement être adapté à tout type. J'ai une série de comparaisons compliquées et cela le rend agréable et lisible.

 /// <summary>
/// A set of extensions to allow the convenient comparison of float values based on a given precision.
/// </summary>
public static class FloatingPointExtensions
{
    /// <summary>
    /// Determines if the float value is less than or equal to the float parameter according to the defined precision.
    /// </summary>
    /// <param name="float1">The float1.</param>
    /// <param name="float2">The float2.</param>
    /// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
    /// <returns></returns>
    public static bool LessThan(this float float1, float float2, int precision)
    {
        return (System.Math.Round(float1 - float2, precision) < 0);
    }

    /// <summary>
    /// Determines if the float value is less than or equal to the float parameter according to the defined precision.
    /// </summary>
    /// <param name="float1">The float1.</param>
    /// <param name="float2">The float2.</param>
    /// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
    /// <returns></returns>
    public static bool LessThanOrEqualTo(this float float1, float float2, int precision)
    {
        return (System.Math.Round(float1 - float2, precision) <= 0);
    }

    /// <summary>
    /// Determines if the float value is greater than (>) the float parameter according to the defined precision.
    /// </summary>
    /// <param name="float1">The float1.</param>
    /// <param name="float2">The float2.</param>
    /// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
    /// <returns></returns>
    public static bool GreaterThan(this float float1, float float2, int precision)
    {
        return (System.Math.Round(float1 - float2, precision) > 0);
    }

    /// <summary>
    /// Determines if the float value is greater than or equal to (>=) the float parameter according to the defined precision.
    /// </summary>
    /// <param name="float1">The float1.</param>
    /// <param name="float2">The float2.</param>
    /// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
    /// <returns></returns>
    public static bool GreaterThanOrEqualTo(this float float1, float float2, int precision)
    {
        return (System.Math.Round(float1 - float2, precision) >= 0);
    }

    /// <summary>
    /// Determines if the float value is equal to (==) the float parameter according to the defined precision.
    /// </summary>
    /// <param name="float1">The float1.</param>
    /// <param name="float2">The float2.</param>
    /// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
    /// <returns></returns>
    public static bool AlmostEquals(this float float1, float float2, int precision)
    {
        return (System.Math.Round(float1 - float2, precision) == 0);
    } 
}
 

2voto

nycdan Points 1765

Je pense que cela résoudra votre problème.

Fondamentalement, il existe une méthode decimal.compare.

EDIT: Cela peut être la meilleure méthode:

Decimal.Equals

EDIT2: Si vous pouvez comparer directement comme suggéré ci-dessus, cela peut être plus efficace. Je laisserai cela comme il peut être intéressant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X