2012-04-12 5 views
0

Ich habe eine Funktion in einer generischen Klasse, die eine Determinante einer Matrix berechnet. Die Funktion funktioniert für einige Eingaben mit beliebigem Typ und für andere gibt sie die falsche Antwort (basierend auf dem Typ). HierUnterschiedliche Antwort basierend auf dem verwendeten arithmetischen Typ (kein Überlauf)

ist die Funktion:

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; 
     } 
    } 

ich hinzugefügt, um den checked Block zu sehen, ob ein Überlauf war stattfindet, aber anscheinend gibt es keinen Überlauf passiert.

Eine Probe eingegeben wird, wenn die 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}}; ist, wird es die richtige Antwort geben (ganz in der Nähe -942.755), aber wenn baseArray statt 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}}; ist gibt es 15.934.050 als Antwort (nicht einmal in der Nähe).

Der Indexer auf der Matrix gibt nur die i-ten j-ten Elemente der Matrix zurück, also sind sie nicht das Problem.

Ich bin verwirrt, was das Problem sein könnte, da es kein Überlauf ist. Irgendwelche Ideen?

-Code zu reproduzieren:

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 ist natürlich richtig. Offensichtlich erhalten Sie unterschiedliche Ergebnisse, wenn Sie ganze Zahlen durch ganze Zahlen und doppelt durch doppelte Zahlen teilen. Was ich nicht verstehe, ist * warum gibt es überhaupt eine Einteilung in diesen Algorithmus *? Die Determinante kann unter Verwendung von Addition, Multiplikation und Subtraktion berechnet werden. –

+0

@EricLippert, Link zum Beispiel? – soandos

Antwort

8

Wenn die Werte int Werte sind, ist es Integer-Arithmetik durchführt. Wenn die Werte double Werte sind, führt es Gleitkommaarithmetik durch - es ist so einfach. Simplere Beispiel:

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

autsch, total vergessen. – soandos

Verwandte Themen