如何正确比较C#中的十进制值?

时间:2011-05-09 17:13:35

标签: c# comparison floating-point

我来自C ++的背景,我知道你无法准确地比较浮点数是否相等。对于C#,我只是假设相同的策略适用于十进制值或一般的任何浮点值。

基本上,我有两个十进制值,如果它们彼此不相等,我需要执行一些操作。 e.g:

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

如果这不能按预期工作,我愿意接受一个与错误边界进行相等比较的解决方案,例如.00001或类似的东西。这个问题的推荐解决方案是什么?

4 个答案:

答案 0 :(得分:27)

您的代码将按预期工作。 C#decimal被优化为非常准确地表示基数为10的数字,所以如果你正在比较(金钱,...),那么一切都应该没问题。

以下是Jon Skeet关于小数精度的非常明确的解释:

  

Difference between decimal, float and double in .NET?

答案 1 :(得分:5)

我正在研究类似的东西,但是精确而不是误差,最后为Float编写了一些扩展。这可以很容易地适用于任何类型。我有一系列复杂的比较,这使它变得美观和可读。

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

答案 2 :(得分:4)

我同意其他答案,但我遇到了一个问题,其中一个是真实的&#34;服务器端小数与来自JSON /浏览器的小数进行比较(并且在某些时候必须是浮点数)。

我最终得到的代码是小数点后舍入到2位,这在我的情况下足够精确:

if (Decimal.Round(serverTotalPrice, 2) != Decimal.Round(request.TotalPrice, 2)) {
    throw new ArgumentException("The submitted Total Price is not valid");
}

答案 3 :(得分:2)

我认为this会解决您的问题。

基本上有一个decimal.compare方法。

编辑:这可能是更好的方法:

Decimal.Equals

EDIT2:如果您可以按照上面的建议直接比较,那可能会更有效率。我会留下它,因为它可能是有意义的。