c# - 如何使用泛型测试 NaN(或者为什么 NaN.Equals(NaN) == true)?

标签 c# iequatable

我需要在数组中找到minma​​x值(不考虑可能的NaN值在这个数组中)。

这只使用 double 会很容易,但是这些 FindMin 和 FindMax 函数必须使用泛型类型。

我尝试以这种方式测试通用 NaN:

bool isNaN<T>(T value) where T : IEquatable<T>
{
    return !value.Equals(value);
}

但是 Equalsdouble.NaN 返回 true ??!!

我现在有这样的解决方法:

bool isNaN<T>(T value) where T : IEquatable<T>
{
    var d = value as double?;
    if (d.HasValue) { return double.IsNaN(d.Value); }

    return !value.Equals(value);
}

我的问题更多是了解为什么第一个解决方案不起作用,这是一个错误吗?

你可以找到小测试代码here

最佳答案

我会简单地使用 double.IsNaN并让编译器隐式转换 float需要的成员:

float myFloat = float.NaN; // or 0.0f / 0.0f;
double myDouble = double.NaN; // or 0.0 / 0.0;

Console.WriteLine(double.IsNaN(myFloat));
Console.WriteLine(double.IsNaN(myDouble));

在堆栈上“浪费”了非常少量的内存并使用了强制转换操作调用,但是嘿嘿它是通用的足够来满足任何可以容纳“数字”NaN 的类型。

或者,使用 float.IsNaN似乎适用于基本测试,但需要显式向下转换 double (向下转换 double.NaN0.0 / 0.0 似乎有效,因为它会正确报告 NaN)。

您不能以任何清洁度(或者根本不能 100% 确定)对值类型的子集进行一般约束,所以我不会费心去追逐 <T>个人路线。


如果你想要一个通用的解决方案,这意味着被调用者不需要关心传入的内容,你可以执行以下操作:

    static bool IsNaN(dynamic d)
    {
        float dub;

        try
        {
            dub = (float)d;
            return float.IsNaN(dub);
        }
        catch (RuntimeBinderException)
        {
        }

        return false;
    }

然而,这会招致装箱。还要注意 dynamic是必需的并且object将不起作用,因此这也会调用 DLR(并且还会吞下所有 RuntimeBinderException s)。

关于c# - 如何使用泛型测试 NaN(或者为什么 NaN.Equals(NaN) == true)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12109345/

相关文章:

c# - 如何从 Xamarin Forms 自定义渲染器中的 View 访问方法?

c# - 我可以为 C# 函数中的参数或可选参数提供默认值吗?

c# - IEnumerable.Except() 和自定义比较器

C# XNA : Trouble with Dictionaries

arrays - 在 [SomeProtocol] 类型的数组中查找对象的索引

c# - IEqualityComparer<T> 和 IEquatable<T> 有什么区别?

c# - 如何为 HttpClient (WinForms) 设置默认的 json 序列化设置

c# - 使用NEST在ElasticSearch的IEnumerable属性上配置分析器的问题

c# - Delphi 相当于 C# 的 DataGridView

c# - 如何在C#中实现多类型IComparable/IEquatable