本文章是由機器翻譯。

C#

矩陣解構

James McCaffrey

下載代碼示例

矩陣分解,分解成兩個不同的方陣,一個方形數位矩陣的一種技術是有效地解決系統的方程,這反過來逆矩陣的基礎的基礎。逆矩陣是許多重要演算法的一部分。這篇文章介紹並說明執行矩陣分解、 矩陣求逆、 一個方程的求解和相關的業務系統的 C# 代碼。

誠然,矩陣分解並不是一個華而不實的話題,但矩陣方法的集合,可以將您的個人代碼庫的重要補充。方法的解釋,以便您可以修改的原始程式碼,以滿足您自己的需要。此外,一些在矩陣方法中使用的技術可以在其他編碼方案中重用。

您去好好感受一下本文仲介紹的資訊種類是要看一看的截圖中的最佳方法圖 1。該演示程式開始通過創建一個 4 x 4 的方陣和顯示其值。下一步,該矩陣被分解成了所謂的土地矩陣。L 代表低和 U 站為上限。P 部分 (P 代表置換) {3,120} 的值的陣列,指示行 0 和 3 在分解過程中就被交換了。分解也生成切換值為-1,指示發生奇數行交流。該演示程式顯示分解兩種方式:第一次作為一個組合的 LU 矩陣,然後作為單獨的 L 和 U 矩陣。接下來,程式計算並顯示原始矩陣,使用在幕後的土地矩陣的逆。該演示程式計算行列式的原始矩陣,請再次使用分解。然後使用矩陣的逆矩陣來解決系統的線性方程組,並通過合併回原始矩陣 L 和 U 矩陣的結論。

Matrix Decomposition Demo圖 1 矩陣分解演示

但為什麼去創建一個自訂矩陣分解方法和相關方法庫的所有的麻煩呢?雖然有許多獨立的矩陣工具可用,但他們有時可能很難將集成到應用程式或系統。矩陣分解的根本重要性,儘管有幾個免費、 無版權.NET 代碼實現可用 ; 那些確實存在往往不是足夠為您要修改的原始程式碼,以適合您的編碼方案的詳細解釋。

本文假定您有中間的 C# 程式設計技巧和矩陣操作和術語的至少一個基本的瞭解。所有關鍵的 C# 代碼是本文仲介紹的。從 MSDN 代碼下載網站上的代碼是也可用 archve.msdn.microsoft.com/mag201212matrix。

矩陣定義

有幾種方法在 C# 中執行一個矩陣。傳統的做法和使用在本文中,一是使用一個陣列的陣列,有時被稱為一個交錯的陣列。例如,此代碼定義了一個具有三行和兩列的矩陣:

double[][] m = new double[3][];
m[0] = new double[2];
m[1] = new double[2];
m[2] = new double[2];
m[2][1] = 5.0; // set row 2, col 1

與大多數程式設計語言不同,C# 具有內置的多維陣列的類型,其中提供了另一種方法。例如:

double[,] m = new double[3,2];
m[2,1] = 5.0;

在 C# 中執行矩陣的第三種方法是使用單個陣列結合陣列索引操作,像這樣:

int rows = 3;
int cols = 2;
double[] m = new double[rows * cols];
int i = 2;
int j = 1;
m[i * cols + j] = 5.0;

無論使用的存儲方案,可以使用物件導向或靜態方法的方法實現矩陣。 例如,OOP 方法可能類似于:

public class MyMatrix
{
  int m; // number rows
  int n; // number columns
  data[][]; // the values
  ...
}

矩陣設計 ; 沒有單一的最佳選擇 最好的設計取決於您正在運行中的特定編碼方案和個人編碼首選項。 這篇文章使用靜態方法的方法,因為它是最容易理解和重構。

時使用陣列的陣列設計矩陣,因為每一行必須單獨分配,它通常是一個方便來定義一個説明器方法來執行記憶體分配。 例如:

static double[][] MatrixCreate(int rows, int cols)
{
  // creates a matrix initialized to all 0.0s
  // do error checking here?
double[][] result = new double[rows][];
  for (int i = 0; i < rows; ++i)
    result[i] = new double[cols]; // auto init to 0.0
  return result;
}

可以調用該方法就像這樣:

double[][] m = MatrixCreate(3,2);
m[2][1] = 5.0;

這種方法演示如何創建您自己的庫的矩陣方法的一個優點:如果您想要提高性能,您可以省略錯誤檢查輸入的參數 — — 而增加導致異常的調用代碼的風險。 (要保留這篇簡短的文章,大多數錯誤檢查已被移除。)另一個優點是您可以自訂您的庫,以優化您確切的方案。 創建您自己的庫的主要缺點是它可以採取比使用現有的庫長。

另一種方便的方法添加到矩陣庫是一個可以用來作為字串顯示矩陣。 這裡是一種可能性:

static string MatrixAsString(double[][] matrix)
{
  string s = "";
  for (int i = 0; i < matrix.Length; ++i)
  {
    for (int j = 0; j < matrix[i].Length; ++j)
      s += matrix[i][j].ToString("F3").PadLeft(8) + " ";
    s += Environment.NewLine;
  }
  return s;
}

您可能想要參數化的小數位數來顯示,和/或列寬度填充,數。

矩陣乘法

4 及更高版本的 Microsoft.NET 框架提供了一種巧妙的方法,大大改善性能的矩陣乘法運算方法。 矩陣乘法所示圖 2

Matrix Multiplication
圖 2 矩陣乘法

請注意每個儲存格的結果值的計算方法不依賴任何其他儲存格值在結果中,而作的所以每個計算是獨立,他們可能可以具有多個處理器的電腦上並存執行。 這裡是矩陣乘法的標準方法:

static double[][] MatrixProduct(double[][] matrixA, 
  double[][] matrixB)
{
  int aRows = matrixA.Length; int aCols = matrixA[0].Length;
  int bRows = matrixB.Length; int bCols = matrixB[0].Length;
  if (aCols != bRows)
    throw new Exception("Non-conformable matrices in MatrixProduct");
  double[][] result = MatrixCreate(aRows, bCols);
  for (int i = 0; i < aRows; ++i) // each row of A
    for (int j = 0; j < bCols; ++j) // each col of B
      for (int k = 0; k < aCols; ++k)
        result[i][j] += matrixA[i][k] * matrixB[k][j];
  return result;
}

因為矩陣乘法是 O(n^3) 操作,性能可能是一個問題。 例如,如果矩陣 A 具有大小 300 x 200 和矩陣 B 具有大小 200 x 400,計算產品的 A 和 B 要求 300 * 200 * 400 = 24,000,000 乘法運算。 任務並行庫 (TPL) System.Threading.Tasks 命名空間在.NET Framework 4 和更高版本中輕鬆編寫一個簡單的矩陣乘法的並行化的版本的代碼。 一種可能是:

static double[][] MatrixProduct(double[][] matrixA, 
  double[][] matrixB)
{
  // error check, compute aRows, aCols, bCols
  double[][] result = MatrixCreate(aRows, bCols);
  Parallel.For(0, aRows, i =>
    {
      for (int j = 0; j < bCols; ++j)
        for (int k = 0; k < aCols; ++k)
          result[i][j] += matrixA[i][k] * matrixB[k][j];
    }
  );
  return result;
}

此版本由行印章起計算。在幕後,TPL 生成所有複雜的同步水暖代碼來在多個處理器上執行的計算。

一致性測試

圖書館彼此相關的方法的一個有趣的現象是很多時候可能以測試它們通過檢查來看是否他們產生一致的結果。例如,假設您有一個方法,創建一個隨機矩陣:

static double[][] MatrixRandom(int rows, int cols,
  double minVal, double maxVal, int seed)
{
  // return matrix with values between minVal and maxVal
  Random ran = new Random(seed);
  double[][] result = MatrixCreate(rows, cols);
  for (int i = 0; i < rows; ++i)
    for (int j = 0; j < cols; ++j)
      result[i][j] = (maxVal - minVal) * ran.NextDouble() + minVal;
  return result;
}

此外,假設您有一個矩陣,創建矩陣的身份 — — 就是一個正方形矩陣與慢速的主對角線,其他地方的 0.0s年上:

static double[][] MatrixIdentity(int n)
{
  double[][] result = MatrixCreate(n, n);
  for (int i = 0; i < n; ++i)
    result[i][i] = 1.0;
  return result;
}

並假設您有一個平等的兩個矩陣進行比較的方法:

static bool MatrixAreEqual(double[][] matrixA,
  double[][] matrixB, double epsilon)
{
  // true if all values in A == corresponding values in B
  int aRows = matrixA.Length;
  int bCols = matrixB[0].Length;
  for (int i = 0; i < aRows; ++i) // each row of A and B
    for (int j = 0; j < aCols; ++j) // each col of A and B
      if (Math.Abs(matrixA[i][j] - matrixB[i][j]) > epsilon)
        return false;
  return true;
 }

通知的 MatrixAreEqual 方法並不比儲存格的值完全相等的因為都是 double 類型的值。相反,該方法將查看是否所有儲存格的值都非常接近 (epsilon) 內彼此。

因為該產品的任何方陣 m 和同一維度的恒等矩陣等於原始矩陣 m,您可以測試矩陣產品方法沿此程式碼:

double[][] m = MatrixRandom(4, 4, -9.0, 9.0, 0);
double[][] i = MatrixIdentity(4);
double[][] mi = MatrixProduct(m, i);
if (MatrixAreEqual(m, mi, 0.00000001) == true)
  Console.WriteLine("Consistent result");
else
  Console.WriteLine("Something is wrong");
Consistency checking lends itself well to random input testing.

矩陣解構

矩陣分解需要方陣 M 和計算兩個新方陣的相乘時給原始矩陣 M。 這個想法是類似于普通號碼保理業務:6 數可計入 2 和 3,因為 2 * 3 = 6。 起初它可能看起來像有小點中分解矩陣,但它原來矩陣分解使得矩陣求逆的非常困難的任務很簡單些。 有許多不同種類的矩陣分解,和每一種可以計算使用幾種不同的演算法。 本文仲介紹的技術被稱為土地分解,並使用具有部分回轉的杜利特爾的方法。

要瞭解土地分解,最好先瞭解更簡單的 LU 分解,由著名數學家阿蘭 · 圖靈介紹。 假設您有此 4 × 4 矩陣 m:

9.000      5.000      3.000      4.000
4.000      8.000      2.000      5.000
3.000      5.000      7.000      1.000
2.000      6.000      0.000      8.000

一個可能的 LU 分解,M 的是 L =

1.000      0.000      0.000      0.000
0.444      1.000      0.000      0.000
0.333      0.577      1.000      0.000
0.222      0.846     -0.219      1.000

U =

9.000      5.000      3.000      4.000
0.000      5.778      0.667      3.222
0.000      0.000      5.615     -2.192
0.000      0.000      0.000      3.904

這樣做是因為 L * U = M。 注意較低的 L 矩陣對角線上的慢速和 0.0s年在右上方。 換句話說,在左下角低矩陣的重要儲存格的值。 同樣上部矩陣的重要儲存格的值是的主對角線上和在右上方。

還注意到有沒有重疊的 L 和美國重要的儲存格的值的位置 所以,而不是生成兩個結果矩陣,L 和 U,矩陣分解通常存儲到一個單一的矩陣,持有 L 和 U 以節省記憶體空間上限和下限結果。

土地矩陣分解是輕微但很重要的變化,對 LU 分解。 土地分解矩陣 M 並生成 L 和 U 的矩陣,但 P 陣列。 L 和 U 在圖中的產品是不完全的原始矩陣 M,但相反是 M 的版本其中的某些行已經被重新安排。 在這行已經被重新安排的方式存儲到 P 的陣列 ; 此資訊可用於重建原始矩陣 M。

本文仲介紹的杜利特爾分解的近親稱為 Crout 的分解。 杜利特爾和 Crout 之間的主要區別是杜利特爾 L 矩陣的主對角線上放置慢速和 Crout U 矩陣的主對角線上放置慢速。

土地分解的原因比 LU 分解是微妙的更頻繁的使用。 如您很快就會看到,矩陣分解用於計算矩陣的逆矩陣。 然而,當矩陣分解為傭工用於矩陣求逆,原來反演將失敗如果陸矩陣的主對角線上有一個 0.0 的值。 所以在土地分解,當告終的主對角線, 值 0.0 演算法會交換移動 0.0 值關閉對角線和跟蹤的哪些行被交換 P 陣列中的兩行。

圖 3 列出矩陣分解方法。

圖 3 矩陣分解法

static double[][] MatrixDecompose(double[][] matrix,
  out int[] perm, out int toggle)
{
  // Doolittle LUP decomposition.
// assumes matrix is square.
int n = matrix.Length; // convenience
  double[][] result = MatrixDuplicate(matrix);
  perm = new int[n];
  for (int i = 0; i < n; ++i) { perm[i] = i; }
  toggle = 1;
  for (int j = 0; j < n - 1; ++j) // each column
  {
    double colMax = Math.Abs(result[j][j]); // largest val in col j
    int pRow = j;
    for (int i = j + 1; i < n; ++i)
    {
      if (result[i][j] > colMax)
      {
        colMax = result[i][j];
        pRow = i;
      }
    }
    if (pRow != j) // swap rows
    {
      double[] rowPtr = result[pRow];
      result[pRow] = result[j];
      result[j] = rowPtr;
      int tmp = perm[pRow]; // and swap perm info
      perm[pRow] = perm[j];
      perm[j] = tmp;
      toggle = -toggle; // row-swap toggle
    }
    if (Math.Abs(result[j][j]) < 1.0E-20)
      return null; // consider a throw
    for (int i = j + 1; i < n; ++i)
    {
      result[i][j] /= result[j][j];
      for (int k = j + 1; k < n; ++k)
        result[i][k] -= result[i][j] * result[j][k];
    }
  } // main j column loop
  return result;
}

像這樣,可以調用該方法:

double[][] m = MatrixRandom(4, 4, -9.0, 9.0, 0);
int[] perm;
int toggle;
double luMatrix = MatrixDecompose(m, out perm, out toggle);

MatrixDecompose 方法接受作為其輸入一個方陣。 該方法具有三個傳回值。 顯式的返回是一個排列後的陸矩陣。 該方法作為 out 參數返回兩個值。 一個是排列陣列,它保存有關 permuted 行是如何的資訊。 Out 參數的第二個是 + 1 或-1 根據行交換數量是否甚至 (+ 1) 或 (-1) 為奇數的切換值。 切換值不用於矩陣求逆,但如果用於計算一個矩陣的行列式矩陣分解需要。

MatrixDecompose 方法是相當棘手的事情,但實際上,有只有幾個細節,您需要瞭解修改的代碼。 這裡提出的版本為陸返回矩陣使用 MatrixDuplicate 的説明器方法分配新的記憶體:

static double[][] MatrixDuplicate(double[][] matrix)
{
  // assumes matrix is not null.
double[][] result = MatrixCreate(matrix.Length, matrix[0].Length);
  for (int i = 0; i < matrix.Length; ++i) // copy the values
    for (int j = 0; j < matrix[i].Length; ++j)
      result[i][j] = matrix[i][j];
  return result;
}

另一種方法是進入輸入矩陣計算出結果,以節省記憶體。 用 C# 的語義,這將使該矩陣參數的 ref 參數因為它用於輸入和輸出。 使用此方法,將方法簽名:

static void MatrixDecompose(ref double[][] matrix, out int[] perm,
  out int toggle)

或者,因為顯式的傳回值已被消除,就可以使用它為排列陣列或交易所切換。 例如:

static int[] MatrixDecompose(ref double[][] matrix, out int toggle)

您可能想要消除要簡化方法簽名,如果您不打算使用矩陣分解來計算行列式的切換參數。

您可能想要修改的 MatrixDecompose 的另一個領域是此語句:

if (Math.Abs(result[j][j]) < 1.0E-20)
  return null;

話說,此代碼的含義:"如果,即使後交換兩行,因為有一個 0.0 值的主對角線上,仍然是有 0.0,然後返回空值。"您可能想要修改的任意 epsilon 值為 1.0 e 從零複選的平等-20 到一些其他的值基於您的系統的精度特徵。 而不是返回 null,您可能想要引發異常 ; 和 如果作為矩陣求逆的一部分被調用的方法,反演將會失敗。 最後,如果您使用矩陣分解的一些矩陣求逆以外的目的,您可能想要完全消除這一聲明。

矩陣求逆

使用矩陣分解反轉矩陣的關鍵是要編寫一個 helper 方法,以解決系統的方程。 此關鍵的説明器方法提出在圖 4

圖 4 HelperSolve 方法

static double[] HelperSolve(double[][] luMatrix, 
  double[] b)
{
  // solve luMatrix * x = b
  int n = luMatrix.Length;
  double[] x = new double[n];
  b.CopyTo(x, 0);
  for (int i = 1; i < n; ++i)
  {
    double sum = x[i];
    for (int j = 0; j < i; ++j)
      sum -= luMatrix[i][j] * x[j];
    x[i] = sum;
  }
  x[n - 1] /= luMatrix[n - 1][n - 1];
  for (int i = n - 2; i >= 0; --i)
  {
    double sum = x[i];
    for (int j = i + 1; j < n; ++j)
      sum -= luMatrix[i][j] * x[j];
    x[i] = sum / luMatrix[i][i];
  }
  return x;
}

HelperSolve 方法查找陣列 x 當乘以陸矩陣賦予陣列 b。方法是很聰明的並可以通過跟蹤幾個例子只有完全理解它。有兩個迴圈。第一個迴圈使用轉發替代關於陸矩陣的下半部分。第二個迴圈使用落後的替代上陸矩陣的上半部分。一些不同的矩陣分解實現調用其類似的方法像 luBackSub 一樣的東西。

雖然代碼很短,但它是棘手的但就不會有任何情況下,您將需要修改的代碼。通知該説明器­解決接受從 MatrixDecompose LU 矩陣,但不使用該燙髮的 out 參數。這意味著 HelperSolve 其實是要解決系統方程的説明器方法和需要額外包裝代碼。如果您重構到物件導向設計的這篇文章中的代碼,您可能想要 HelperSolve 的私有方法。

與地方中的 HelperSolve 方法,矩陣反演方法可以實現,如中所示圖 5

圖 5 MatrixInverse 方法

static double[][] MatrixInverse(double[][] matrix)
{
  int n = matrix.Length;
  double[][] result = MatrixDuplicate(matrix);
  int[] perm;
  int toggle;
  double[][] lum = MatrixDecompose(matrix, out perm, out toggle);
  if (lum == null)
    throw new Exception("Unable to compute inverse");
  double[] b = new double[n];
  for (int i = 0; i < n; ++i)
  {
    for (int j = 0; j < n; ++j)
    {
      if (i == perm[j])
        b[j] = 1.0;
      else
        b[j] = 0.0;
    }
    double[] x = HelperSolve(lum, b);
    for (int j = 0; j < n; ++j)
      result[j][i] = x[j];
  }
  return result;
}

再次,代碼是棘手的。 反演演算法基於一個矩陣 M 和它的逆產品是恒等矩陣的想法。 方法 MatrixInverse 基本上解決了方程組 Ax = 的 b A 是陸矩陣分解和 b 常量是 1.0 或 0.0 和對應單位矩陣。 請注意 MatrixInverse 使用的燙髮陣列從對 MatrixDecompose 的調用。

調用 MatrixInverse 方法可能看起來像這樣:

double[][] m = MatrixRandom(4, 4, -9.0, 9.0, 0);
double[][] inverse = MatrixInverse(m);
Console.WriteLine(MatrixAsString(inverse));

概括地說,重要的矩陣操作是矩陣求逆,這是相當難的。 一種方法是將原始矩陣分解、 寫一個助手解決執行向前和向後替換的方法和使用的分解與陸排列陣列和傭工然後解決方法找到的逆。 這種方法可能看起來很複雜,但它通常是更有效率和更容易比直接計算矩陣的逆。

矩陣行列式

與手中的矩陣分解方法,很容易的方法來計算矩陣的行列式的代碼:

static double MatrixDeterminant(double[][] matrix)
{
  int[] perm;
  int toggle;
  double[][] lum = MatrixDecompose(matrix, out perm, out toggle);
  if (lum == null)
    throw new Exception("Unable to compute MatrixDeterminant");
  double result = toggle;
  for (int i = 0; i < lum.Length; ++i)
    result *= lum[i][i];
  return result;
}

事實證明,有點令人驚訝,矩陣的行列式是只加上或減去 (根據切換值) 的土地分解矩陣的主對角線上的值的乘積。 請注意沒有隱式類型轉換價值的切換從 int 將翻一番。 除了添加錯誤檢查至 MatrixDeterminant,您可能要添加短路的輸入的矩陣有大小 (然後返回單個值) 1 或 2 x 2 的大小的情況下返回 (然後返回 * d-b * c)。 調用的行列式的方法,象這樣:

double[][] m = MatrixRandom(4, 4, -9.0, 9.0, 0);
double det = MatrixDeterminant(m);
Console.WriteLine("Determinant = " + det.ToString("F2"));

方程組求解

HelperSolve 方法可以輕鬆地調整,以解決系統的線性方程組:

static double[] SystemSolve(double[][] A, double[] b)
{
  // Solve Ax = b
  int n = A.Length;
  int[] perm;
  int toggle;
  double[][] luMatrix = MatrixDecompose(A, 
    out perm, out toggle);
  if (luMatrix == null)
    return null; // or throw
  double[] bp = new double[b.Length];
  for (int i = 0; i < n; ++i)
    bp[i] = b[perm[i]];
  double[] x = HelperSolve(luMatrix, bp);
  return x;
}

這裡是製作的截圖中的代碼圖 1 來解決以下系統:

3x0 + 7x1 + 2x2 + 5x3 = 49
 x0 + 8x1 + 4x2 + 2x3 = 30
2x0 +  x1 + 9x2 + 3x3 = 43
5x0 + 4x1 + 7x2 +  x3 = 52

double[][] m = MatrixCreate(4, 4);
m[0][0] = 3.0; m[0][1] = 7.0; m[0][2] = 2.0; m[0][3] = 5.0;
m[1][0] = 1.0; m[1][1] = 8.0; m[1][2] = 4.0; m[1][3] = 2.0;
m[2][0] = 2.0; m[2][1] = 1.0; m[2][2] = 9.0; m[2][3] = 3.0;
m[3][0] = 5.0; m[3][1] = 4.0; m[3][2] = 7.0; m[3][3] = 1.0;
double[] b = new double[] { 49.0, 30.0, 43.0, 52.0 };
double[] x = SystemSolve(m, b);
Console.WriteLine("\nSolution is x = \n" + VectorAsString(x));

SystemSolve 重新排列其 b 輸入的參數在調用 HelperSolve 之前使用 MatrixDecompose 中的燙髮陣列的通知。

理解排列陣列

輸出中的螢幕擷取畫面中的最後幾行圖 1 表示有可能以一種能獲取原始矩陣中的 L 和 U 的矩陣相乘。 瞭解如何執行此操作,不將使您能夠解決實際矩陣的問題,但它將説明您瞭解土地分解的 P 部分。 再生原始矩陣從其 L 和 U 的元件也可以用於測試您的矩陣庫方法的一致性。

土地分解後重新生成原始矩陣的一種方法是將乘以 L 和 U,然後 permute 產品使用 P 陣列中的行:

// create matrix m
// call MatrixDecompose, returning lu and perm
// extract the lower part of lu as matrix 'lower'
// extract the upper part of lu as matrix 'upper'
double[][] lu = MatrixProduct(lower, upper);
double[][] orig = UnPermute(lu, perm);
if (MatrixAreEqual(orig, m, 0.000000001) == true)
  Console.WriteLine("L and U unpermuted using perm array");

UnPermute 方法可以像這樣進行編碼:

static double[][] UnPermute(double[][] luProduct, int[] perm)
{
  double[][] result = MatrixDuplicate(luProduct);
  int[] unperm = new int[perm.Length];
  for (int i = 0; i < perm.Length; ++i)
    unperm[perm[i]] = i; // create un-perm array
  for (int r = 0; r < luProduct.Length; ++r) // each row
    result[r] = luProduct[unperm[r]];
  return result;
}

第二種方法,用於重新生成原始矩陣從其土地分解是向燙髮矩陣轉換的燙髮陣列,然後乘以燙髮矩陣和組合的陸矩陣:

// create matrix m
// call MatrixDecompose, returning lu and perm
// extract the lower part of lu as matrix 'lower'
// extract the upper part of lu as matrix 'upper'
double[][] permMatrix = PermArrayToMatrix(perm);
double[][] orig = MatrixProduct(permMatrix, lu);
if (MatrixAreEqual(orig, m, 0.000000001) == true)
  Console.WriteLine("L and U unpermuted using perm matrix");

燙髮矩陣是一個正方形矩陣與一個 1.0 中的每一行和每一列的值。 從燙髮陣列創建一個燙髮矩陣的方法可以進行編碼就像這樣:

static double[][] PermArrayToMatrix(int[] perm)
{
  // Doolittle perm array to corresponding matrix
  int n = perm.Length;
  double[][] result = MatrixCreate(n, n);
  for (int i = 0; i < n; ++i)
    result[i][perm[i]] = 1.0;
  return result;
}

總結

有很多的演算法需要求解線性方程組、 尋找一個矩陣的逆或找到一個矩陣的行列式。 使用矩陣分解是一種有效的執行所有這些操作技術。 這裡介紹的代碼可以使用您想沒有外部依賴項的代碼基中或您需要自訂的操作來提高性能或修改功能的能力的情況。 紅色藥丸 !

**博士。**詹姆斯 · 麥卡弗裡為伏資訊科學 Inc.,他在管理工作在微軟雷德蒙德,華盛頓州,校園的軟體工程師的技術培訓工作。他曾經參與過多項 Microsoft 產品的研發,包括 Internet Explorer 和 MSN Search。麥卡弗裡是.NET 測試自動化食譜 (Apress,2006年) 的作者。他可以在達成 jammc@microsoft.com

感謝以下技術專家對本文的審閱:保羅 · 科赫和 Dan Liebling