2012-04-12 46 views
0

我在泛型类中有一个函数,用于计算矩阵的行列式。该函数适用于某些类型的输入,而对于其他类型的输入则会给出错误的答案(根据类型)。基于所用算术类型的不同答案(不发生溢出)

下面是函数:

public T Determinant() 
    { 
     checked 
     { 
      int n = dimension; 
      Matrix<T> a = new Matrix<T>(baseArray); 
      int i, j, k; 
      T det = (dynamic)0; 
      for (i = 0; i < n - 1; i++) 
      { 
       for (j = i + 1; j < n; j++) 
       { 
        det = (dynamic)a[j, i]/a[i, i]; 
        for (k = i; k < n; k++) 
         a[j, k] = a[j, k] - (dynamic)det * a[i, k]; 
       } 
      } 
      det = (dynamic)1; 
      for (i = 0; i < n; i++) 
       det = (dynamic)det * a[i, i]; 

      return det; 
     } 
    } 

我加入了checked块,看是否有溢出发生,但显然,没有溢出发生。

如果baseArray是new double[,] {{11, 11, 12, 17, 21, 29}, {16, 9, 25, 30, 29, 33}, {3, 13, 9, 24, 21, 24}, {23, 6, 29, 21, 23, 23}, {22, 19, 14, 30, 21, 24}, {22, 28, 20, 17, 25, 28}};它会给出正确答案(非常接近-942755),但是如果baseArray代替new int[,] {{11, 11, 12, 17, 21, 29}, {16, 9, 25, 30, 29, 33}, {3, 13, 9, 24, 21, 24}, {23, 6, 29, 21, 23, 23}, {22, 19, 14, 30, 21, 24}, {22, 28, 20, 17, 25, 28}};,它会给出15934050作为答案(甚至不接近)。

矩阵上的索引器只返回矩阵的第i个第j个元素,所以它们不是问题。

我很困惑这个问题可能是因为它不是溢出。有任何想法吗?

代码重现:

public class Matrix<T> 
where T : IConvertible 
{ 
    private int dimension; 
    private T[][] baseArray; 

    public Matrix(int dimensions, T[,] baseArray) 
    { 
     this.dimension = dimensions; 
     this.baseArray = new T[dimension][]; 
     for (int i = 0; i < dimension; i++) 
     { 
      this.baseArray[i] = new T[dimension]; 
      for (int j = 0; j < dimension; j++) 
      { 
       this[i, j] = baseArray[i, j]; 
      } 
     } 
    } 

    public T this[int a, int b] 
    { 
     get 
     { 
      return baseArray[a][b]; 
     } 
     set 
     { 
      baseArray[a][b] = value; 
     } 
    } 

    public T Determinant() 
    { 
     checked 
     { 
      int n = dimension; 
      Matrix<T> a = new Matrix<T>(baseArray); 
      int i, j, k; 
      T det = (dynamic)0; 
      for (i = 0; i < n - 1; i++) 
      { 
       for (j = i + 1; j < n; j++) 
       { 
        det = (dynamic)a[j, i]/a[i, i]; 
        for (k = i; k < n; k++) 
         a[j, k] = a[j, k] - (dynamic)det * a[i, k]; 
       } 
      } 
      det = (dynamic)1; 
      for (i = 0; i < n; i++) 
       det = (dynamic)det * a[i, i]; 

      return det; 
     } 
    } 
} 
+1

乔恩当然是正确的。很明显,当你用整数和双打来划分整数时你会得到不同的结果。我不明白的是*为什么这个算法在第一个地方有任何分歧*?行列式可以仅使用加法,乘法和减法来计算。 – 2012-04-12 22:38:33

+0

@EricLippert,链接到示例? – soandos 2012-04-15 01:01:18

回答

8

当值是int值时,它执行整数运算。 当值为double的值时,它执行浮点运算 - 就像那样简单。更简单的例子:

using System; 

public class Test 
{ 
    static void Main() 
    { 
     PrintResult(1, 2);  // Prints 0 
     PrintResult(1.0, 2.0); // Prints 0.5 
    } 

    static void PrintResult(dynamic x, dynamic y) 
    { 
     Console.WriteLine(x/y); 
    } 
} 
+0

哎哟,完全忘了那个。 – soandos 2012-04-12 22:03:57