1

X などの double 値のベクトル (1D 配列) があります。Y の最初の行が X の転置と同じになるように、この値のベクトルを Y などの行列 (2D 配列) にコピーする必要があります。行は X を 1 値左にシフトしたものと同じで、Y の 3 行目は X を 2 値左にシフトしたものと同じです。

例えば、

X = { 1.0, 2.0. 3.0, 4.0, 5.0 }

そして私は必要です

Y =  1.0  2.0  3.0  4.0  5.0
     2.0  3.0  4.0  5.0  0.0
     3.0  4.0  5.0  0.0  0.0
     4.0  5.0  0.0  0.0  0.0
     5.0  0.0  0.0  0.0  0.0

しばらく前に、Mathew Finlay が値型の 1D 配列を 2D 配列にコピーするためのコードを投稿しました。次のようにコードを変更しました。

for (int targetRow = 0; targetRow < N; targetRow++)
{
    Buffer.BlockCopy
    (
        X,                                                    // 1D source array
        0,                                                    // source array offset
        Y,                                                    // 2D target (destination) array
        targetRow * Y.GetLength(targetRow) * sizeof(double),  // target array offset
        X.Length * sizeof(double)                             // count
    );
}

これがうまくいくかどうか、さらに重要なことに、これがこれを行うための最良の方法であるかどうかはわかりません. これはより大きなコードの一部であり、ベクトル X と行列 Y が非常に大きくなる可能性があるため、この部分は高速かつ効率的である必要があります。

また、物事をもう少し複雑にするために、ベクトル X の全長 (すべての値) を必要とせず、その一部のみを必要とする場合があるため、行列 Y は N x M (M <= N) になる可能性があります。上記のコードでこれを処理します。

あなたが提供できるかもしれない助けや提案を事前に感謝します.

編集: 興味のある方のために、パフォーマンス結果をいくつか示します。

ここで提案されている 2 種類のコード (ループと Buffer.BlockCopy) でいくつかの速度テストを実行したところ、驚くべき結果が得られました。Buffer.BlockCopy を BC として指定し、ループを L として指定します。100x100 マトリックスの場合、BC = 00:00:00.0000293 および L = 00:00:00.0000710 です。最後に、1000x1000 マトリックスの場合、BC = 00:00:00.0065340 および L = 00:00:00.0138396 です。そのため、Buffer.Block のコピーは、行列が小さい場合でもループよりも優れているようです。これを Win 7 Ultimate (64) マシンで実行しました。

4

2 に答える 2

1

どうですか?

       double[] X = new double[]{ 1.0, 2.0, 3.0, 4.0, 5.0 };

        var lbound = X.GetLowerBound(0);
        var ubound = X.GetUpperBound(0);

       double[,] Y = new double[ubound + 1, ubound + 1];

       for (var i = lbound; i <= ubound; i++)
       {
           for (var j = lbound ; j <= ubound ; j++)
           {
               Y[i, j] = (i + j) > ubound ? 0.0 : X[i +j];
           }  
       }

編集

これは機能します:

 for (int targetRow = 0; targetRow <= ubound; targetRow++)
  {
    Buffer.BlockCopy
    (
        X,                                        // 1D source array
        targetRow * sizeof(double),               // source array offset
        Y,                                        // 2D target (destination) array
        (targetRow * X.Length) * sizeof(double),  // target array offset
        (X.Length - targetRow) * sizeof(double)  // count
    );
}


for (var i = 0; i <= ubound; i++)
{
    for (var j = 0; j <= ubound; j++)
    {
        Console.Write(Y[i, j] + " ");
    }
    Console.WriteLine();
}

Console.ReadKey();

配列オフセット


2回目の編集

宛先配列の 2 番目の次元を変更するという他の要件に対処するには、いくつかのBlockCopyパラメーターtargetArrayOffsetを変更する必要がありcount、以下のようにそれらを宛先配列の次元にマップできます。

        double[] X = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };

        var lbound = X.GetLowerBound(0);
        var ubound = X.GetUpperBound(0);

       double[,] Y = new double[X.Length, 3];

        int yLen = Y.GetUpperBound(1) + 1;

for (int targetRow = 0; targetRow <= ubound; targetRow++)
{
    Buffer.BlockCopy
    (
        X,                                      // 1D source array
        (targetRow * sizeof(double)),             // source array offset
        Y,                                        // 2D target (destination) array
        ((targetRow * yLen) * sizeof(double)),// target array offset
        ((X.Length - targetRow) > yLen ? yLen : (X.Length - targetRow))  * sizeof(double)  // count
    );
}

出力:

スクリーンプリント

于 2013-11-01T21:38:43.800 に答える
0

xがタイプであると仮定するとdouble[]、次を使用します。

var y = new double[x.Length, x.Length];
for (int row = 0; row < x.Length; ++row)
{
  for (int col = 0; col < x.Length - row; ++col)
  {
    y[row, col] = x[col - row];
  }
}

または類似。

于 2013-11-01T21:42:26.790 に答える