【问题标题】:How to check whether a numeric value is zero如何检查数值是否为零
【发布时间】:2018-06-09 20:36:05
【问题描述】:

这里我有一个应该为向量建模的类的最小示例(用于线性代数计算)。它包括一个类型T,它将是一个整数或浮点类型(例如intdouble)。现在我想实现一个方法CheckIfZeroAt 来检查某个条目是否包含零。问题是我想保留类型T 变量,但据我所知,我无法告诉编译器我T 是一个可以使用类型转换的数字类型。不幸的是,似乎也没有我可以将T 限制为数字类型的接口。

有什么优雅的方法可以解决这个问题吗?

我提供了一些可以尝试将这种方法实现为 cmets 的幼稚方法,但它们都不起作用。

class MyVector<T> // T is an integral or floating point type
{
    T[] vector;

    public MyVector(T[] array)
    {
        vector = array; //just a reference 
    }

    public bool CheckIfZeroAt(int i)
    {
        // return vector[0] == (T)0; //"Cast is redundant"
        // return vector[0] == 0; // Operator "==" cannot be applied to operands of type "T" and "int"
        // return vector[0] == 2 * vector[0]; // Operator "*" cannot be applied to operands of type "T" and "int"
    }

}

【问题讨论】:

  • 您是否考虑过获取Ttype,然后基于此进行投射/切换/如果...其他?
  • 我猜你需要某种“数字”接口或类似的东西
  • .NET 的泛型实现不太适合这个。适用于类型擦除、C++ 或 Java 类型的泛型,但不适用于 .NET 使用的具体类型。很多你一般不能做的事情,像加或乘两个 T 值这样基本的事情是行不通的。使用 default(T) 测试零实际上是可能的,有点意外。然而,它效率不高。您需要认真考虑特定的非泛型类,实际上不会有那么多。
  • 不完美,但你有没有考虑过使用IConvertible
  • 我不得不建议你真正完成你的代码。然后你会不可避免地发现你需要做什么。到那时,你肯定会从你的问题中去掉“优雅”这个词。好东西,每个 .NET 程序员都必须自己发现这一点。

标签: c# generics math vector


【解决方案1】:

.NET 中的数值类型有一个default of 0,所以只需检查它是否等于default(T)

public bool CheckIfZeroAt(int i)
{
    return vector[i].Equals(default(T));
}

小提琴here

正如 Hans 在 cmets 中指出的那样,这并不是最好的解决方案。似乎您应该一起跳过泛型,因为 .NET 中没有很多现成的数字类型。

【讨论】:

    【解决方案2】:

    您可以使用IConvertible。这允许所有数值类型。它也允许使用 DateTime、string 和 bit,但如果有人选择使用 MyVector&lt;bool&gt;,你要争论谁?它仍然是一个数字。

    注意:由于浮点类型可能有错误,您可能希望允许容差。在我的示例中,公差为 0.1。 (如果您可以接受 0.5 的容差,则可以直接转换为 int 而不是使用 Math.Abs)。

    class MyVector<T> where T : IConvertible
    {
        T[] vector;
    
        public MyVector(T[] array)
        {
            vector = array; //just a reference 
        }
    
        public bool CheckIfZeroAt(int i, decimal tolerance = 0.1M)
        {
            return Math.Abs(Convert.ToDecimal(vector[i])) < tolerance;
        }
    
        public bool CheckIfZeroAt(int i)
        {
            return Convert.ToInt32(vector[i])) == 0;
        }
    
    }
    

    【讨论】:

    • 谢谢,这看起来是最实用的方法。在我的情况下,我试图实现一个小型线性代数库(就像一个练习),我会计算恰好为零的数字,例如用于决定稀疏格式是否更合适。 (类似于 numpy 中的 count_nonzero 或 Octave/MATLAB 中的 nnz。)
    • 如果值超出 Int32 的范围,这将抛出。
    猜你喜欢
    • 2011-04-13
    • 2014-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    相关资源
    最近更新 更多