【问题标题】:how to handle double.NaN for Generic method accepting IComparable in C#如何在 C# 中处理接受 IComparable 的通用方法的 double.NaN
【发布时间】:2013-01-04 21:45:02
【问题描述】:

我有一个通用的GetMinimum 方法。它接受 IComparable 类型的数组(因此它可能是 string[]double[])。在double[] 的情况下,如何实现此方法以忽略double.NaN 值? (我正在寻找好的做法)

当我传递这个数组时

double[] inputArray = { double.NaN, double.NegativeInfinity, -2.3, 3 };

它返回 double.NaN!

public T GetMinimum<T>(T[] array) where T : IComparable<T>
{
    T result = array[0];
    foreach (T item in array)
    {
        if (result.CompareTo(item) > 0)
        {
            result = item;
        }
    }
    return result;
}

【问题讨论】:

    标签: c# generics nan icomparable


    【解决方案1】:

    你不能从方法内部。原因是您不知道方法内部的T 可以是什么。也许你可以通过一些小演员,但理想情况下这应该是你的方法:

    public T GetMinimum<T>(T[] array, params T[] ignorables) where T : IComparable<T>
    {
        T result = array[0]; //some issue with the logic here.. what if array is empty
        foreach (T item in array)
        {
            if (ignorables.Contains(item)
                continue;
    
            if (result.CompareTo(item) > 0)
            {
                result = item;
            }
        }
        return result;
    }
    

    现在叫这个:

    double[] inputArray = { double.NaN, double.NegativeInfinity, -2.3, 3 };
    GetMinimum(inputArray, double.NaN);
    

    如果您确定只有一个项目被忽略,那么您可以只将T 作为第二个参数(也许作为可选参数)。

    或者用更短的方法,只是:

    inputArray.Where(x => !x.Equals(double.NaN)).Min();
    

    【讨论】:

    • 你确定它不返回 double.NaN 吗?
    • 那行不通——调用ignorables.Contains() 不会成功,因为double.NaN.Equals(double.NaN) 将返回false。您需要使用double.IsNaN() 处理特殊情况。
    • @HosseinNarimaniRad 它可能会返回,这就是为什么我说里面的逻辑不是那么合理。但编辑不是我的主要优先事项
    • @nawfal 嗯,我的立场是正确的。来自 MSDN:“如果通过调用 Equals 方法测试两个 Double.NaN 值是否相等,则该方法返回 true。但是,如果使用相等运算符测试两个 NaN 值是否相等,则该运算符返回 false。”这似乎有点奇怪!
    【解决方案2】:

    根据这个问答,很复杂:Sorting an array of Doubles with NaN in it

    幸运的是,您可以绕过它:

    if( item is Single || item is Double ) {
        Double fitem = (Double)item;
        if( fitem == Double.NaN ) continue;
    }
    

    【讨论】:

    • 这行不通,因为fitem == Double.NaN 将始终评估为假,即使fitem 实际上是Double.NaN。你必须使用Double.IsNaN(fitem)(或fitem.Equals(Double.NaN),正如我发现的那样)。
    【解决方案3】:

    由于NaN &lt; xNaN &gt; x 都将始终为false,因此根本没有定义可以 包含NaN 的集合的最小值。这就像除以零:没有有效的答案。

    因此,合乎逻辑的方法是预先过滤这些值。这不会是通用的,但应该没问题。

     var results = inputArray.EliminateNaN().GetMinimum();
    

    关注点分离:过滤不应该是GetMinimum()的责任(和负担)。

    【讨论】:

    • 是的。完全一样 inputArray.Where(x =&gt; !x.Equals(double.NaN)).Min();
    猜你喜欢
    • 2015-12-20
    • 2014-09-21
    • 2015-08-04
    • 2012-03-21
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    相关资源
    最近更新 更多