2012-04-12 4 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は、それが(-942755に非常に近い)正しい答えを与える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}};ですが、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

Jonはもちろん正しいです。明らかに、整数を整数で、2倍を2倍で除算すると、結果が異なります。私が理解していないのは、なぜこのアルゴリズムの最初の部分に何らかの部分があるのですか?行列式は、加算、乗算、および減算のみを使用して計算できます。 –

+0

@EricLippert、exampleへのリンク? – soandos

答えて

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

関連する問題