如何在 C# 中处理接受 IComparable 的通用方法的 double.NaN

Posted

技术标签:

【中文标题】如何在 C# 中处理接受 IComparable 的通用方法的 double.NaN【英文标题】:how to handle double.NaN for Generic method accepting IComparable in C# 【发布时间】: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;

【问题讨论】:

【参考方案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();

以上是关于如何在 C# 中处理接受 IComparable 的通用方法的 double.NaN的主要内容,如果未能解决你的问题,请参考以下文章

C#中的IComparable和IComparer接口

C#中的IComparable和IComparer接口

C#内建接口:IComparable

C#中常用接口介绍

c# IComparable与IComparer接口

在C#语言开发程序中,以下关于IComparable<T>和IComparer<T>的说法中错误的是()。(选择一项)