web-dev-qa-db-ja.com

Javascriptで2つの行列を乗算する

2つの行列を乗算する関数を実行しています。行列は常に同じ数の行と列を持ちます。 (2x2、5x5、23x23、...)

印刷しても動作しません。どうして?

たとえば、2つの2x2行列を作成するとします。

matrixA:

[1][2]

[3][4]

matrixB:

[5][6]

[7][8]

結果は次のようになります。

[19][22]

[43][50]

http://ncalculators.com/matrix/2x2-matrix-multiplication-calculator.htm

しかし、私は得ます:

[19][undefined]

[22][indefined]
function multiplyMatrix(matrixA, matrixB)
{
    var result = new Array();//declare an array   

    //var numColsRows=$("#matrixRC").val();
    numColsRows=2;
    
    //iterating through first matrix rows
    for (var i = 0; i < numColsRows; i++) 
    {
        //iterating through second matrix columns
        for (var j = 0; j < numColsRows; j++) 
        { 
            var matrixRow = new Array();//declare an array
            var rrr = new Array();
            var resu = new Array();
            //calculating sum of pairwise products
            for (var k = 0; k < numColsRows; k++) 
            {
                rrr.Push(parseInt(matrixA[i][k])*parseInt(matrixB[k][j]));
            }//for 3
            resu.Push(parseInt(rrr[i])+parseInt(rrr[i+1]));

            result.Push(resu);
            //result.Push(matrixRow);
        }//for 2
    }//for 1
    return result;
}// function multiplyMatrix
11
Jordi 45454

さまざまな一時配列と混同されています。 undefined値は、最も内側のループの下の行での境界外のアクセスが原因で発生します。

乗算の結果については、単一の配列を作ることに固執することをお勧めします。おそらくご存知のとおり、問題はJavaScriptでは多次元配列を初期化できないことです。 2次元配列を作成するには、1次元配列を初期化してから、その要素を反復処理し、各要素を1次元配列に初期化する必要があります。

function multiply(a, b) {
  var aNumRows = a.length, aNumCols = a[0].length,
      bNumRows = b.length, bNumCols = b[0].length,
      m = new Array(aNumRows);  // initialize array of rows
  for (var r = 0; r < aNumRows; ++r) {
    m[r] = new Array(bNumCols); // initialize the current row
    for (var c = 0; c < bNumCols; ++c) {
      m[r][c] = 0;             // initialize the current cell
      for (var i = 0; i < aNumCols; ++i) {
        m[r][c] += a[r][i] * b[i][c];
      }
    }
  }
  return m;
}

function display(m) {
  for (var r = 0; r < m.length; ++r) {
    document.write('&nbsp;&nbsp;'+m[r].join(' ')+'<br />');
  }
}

var a = [[8, 3], [2, 4], [3, 6]],
    b = [[1, 2, 3], [4, 6, 8]];
document.write('matrix a:<br />');
display(a);
document.write('matrix b:<br />');
display(b);
document.write('a * b =<br />');
display(multiply(a, b));
16
Michael Laszlo

次の場所からmultiplyMatrices()関数を使用できます: http://tech.pro/tutorial/1527/matrix-multiplication-in-functional-javascript 機能します魅力のように。例(Chromeおよびconsole.table()を使用したFirefoxコンソールでスタイルを使用してマトリックスを印刷できます):

function multiplyMatrices(m1, m2) {
    var result = [];
    for (var i = 0; i < m1.length; i++) {
        result[i] = [];
        for (var j = 0; j < m2[0].length; j++) {
            var sum = 0;
            for (var k = 0; k < m1[0].length; k++) {
                sum += m1[i][k] * m2[k][j];
            }
            result[i][j] = sum;
        }
    }
    return result;
}

var m1 = [[1,2],[3,4]]
var m2 = [[5,6],[7,8]]

var mResult = multiplyMatrices(m1, m2)

/*In Google Chrome and Firefox you can do:*/

console.table(mResult) /* it shows the matrix in a table */

Result matrix in console.table()

9

私はそれが古い質問であることを知っていますが、私は推奨私の答えに切り替えるようにしています。

私のソリューションはMapReduce関数を使用しているため、パフォーマンスが優れています

//The chosen one
function matrixDot (A, B) {
    var result = new Array(A.length).fill(0).map(row => new Array(B[0].length).fill(0));

    return result.map((row, i) => {
        return row.map((val, j) => {
            return A[i].reduce((sum, Elm, k) => sum + (Elm*B[k][j]) ,0)
        })
    })
}

var print = m => m.forEach(r => document.write(`&nbsp;&nbsp;${r.join(' ')}<br/>`)) 

var a = [[8, 3], [2, 4], [3, 6]]
var b = [[1, 2, 3], [4, 6, 8]]

document.write('matrix a:<br />');
print(a);
document.write('matrix b:<br />');
print(b);
document.write('a * b =<br />');
print(matrixDot(a,b));
8

どんちゃん騒ぎのルートに行きたいなら、いくつかの最新のブラウザーで利用できるようになったWebGL機能で頂点変換を使用して何かを行うこともできます。

これがOpenCLのベクトル変換にアプローチするのと同じように機能するかどうかは本当にわかりません(実際には、それらは型と同等/相互運用可能です)が、一般的な考え方は次のとおりです。

  • バッファに値を追加する

  • 「ふりをして」それは頂点の配列です

  • gPUエンジンを使用して大量を変換する

  • ベクトルから修正された値を取得する

(デモはこちら) http://www.html5rocks.com/en/tutorials/webgl/webgl_transforms/

通常のループインループアプローチの単なる代替案です。そして、正直に言うと、OpenCLがこの種のことのために設計されていることを考えると、ちょっとしたフィドルです

OpenCL 1.2仕様では、OpenGLからの頂点バッファーをOpenCLを使用してロードおよび変換できます(参照 https://software.intel.com/en-us/articles/opencl-and-opengl-interoperability-tutorial =)

1
user3580838

この問題は動的プログラミングメモ化を使用して解決できます。これは、以前に計算された結果をキャッシュし、同じ計算が再び必要になったときにキャッシュされた結果を返す最適化手法を説明する用語です。

        let mat1 = [[1, 2, 3], [2, 1, 2]];

        let mat2 = [[1, 2], [1, 2], [1, 2]];

        function matrixMulti(x, y) {
          let saveComputation = {};
          let finalMat = [],
               length=x.length,
               length1 =  y[0].length,
               length2 =  y.length;
          for (let i = 0; i < length; i++) {
            finalMat.Push([]);
            for (let j = 0; j < length1; j++) {
              finalMat[i][j] = 0;
              for (let k = 0; k < length2; k++) {
    // check if we already computed this calculation or not
                if (saveComputation[y[k][j] + '*' + x[i][k]] || saveComputation[x[i][k] + '*' + y[k][j]]) {
                  finalMat[i][j] = finalMat[i][j] + saveComputation[y[k][j] + '*' + x[i][k]];
                } else {
// save if not computed
                  saveComputation[x[i][k] + '*' + y[k][j]] = x[i][k] * y[k][j]; // check format below how it is saved.
                  saveComputation[y[k][j] + '*' + x[i][k]] = x[i][k] * y[k][j];
                  finalMat[i][j] = finalMat[i][j] + saveComputation[y[k][j] + '*' + x[i][k]];
                }
              }
            }
          }

          console.log(finalMat);
        }

        matrixMulti(mat1, mat2);

上記の入力値の場合saveComputation

{ '1*1': 1,
  '2*1': 2,
  '1*2': 2,
  '3*1': 3,
  '1*3': 3,
  '2*2': 4,
  '3*2': 6,
  '2*3': 6 }
1
Shumi Gupta