在 Javascript 中乘以 2 个矩阵
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27205018/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiply 2 matrices in Javascript
提问by Jordi 45454
I'm doing a function that multiplies 2 matrices. The matrices will always have the same number of rows and columns. (2x2, 5x5, 23x23, ...)
我正在做一个乘以 2 个矩阵的函数。矩阵将始终具有相同的行数和列数。(2x2, 5x5, 23x23, ...)
When I print it, it doesn't work. Why?
当我打印它时,它不起作用。为什么?
For example, if I create two 2x2 matrices:
例如,如果我创建两个 2x2 矩阵:
matrixA:
矩阵A:
[1][2]
[3][4]
matrixB:
矩阵B:
[5][6]
[7][8]
The result should be:
结果应该是:
[19][22]
[43][50]
(http://ncalculators.com/matrix/2x2-matrix-multiplication-calculator.htm)
(http://ncalculators.com/matrix/2x2-matrix-multiplication-calculator.htm)
But, I get:
但是,我得到:
[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
回答by Michael Laszlo
You're getting confused with your various temporary arrays. The undefinedvalues are caused by out-of-bounds access on the line below your innermost loop.
您对各种临时数组感到困惑。这些undefined值是由最内层循环下方的行上的越界访问引起的。
I recommend that you stick to making a single array for the result of the multiplication. As you're probably aware, the hitch is that JavaScript doesn't allow you to initialize a multi-dimensional array. To make a two-dimensional array, you have to initialize a one-dimensional array, then iterate over its elements and initialize each one to a one-dimensional array.
我建议您坚持为乘法结果制作单个数组。您可能知道,问题在于 JavaScript 不允许您初始化多维数组。要制作二维数组,您必须初始化一维数组,然后迭代其元素并将每个元素初始化为一维数组。
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(' '+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));
回答by Fernando Carvajal
I know it's an old question but I recommendto switch to my answer.
我知道这是一个老问题,但我建议切换到我的答案。
My solution's got good performance because it uses
MapReducefunctions
我的解决方案性能良好,因为它使用了
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(` ${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));
回答by Johann Echavarria
You can use multiplyMatrices() function from: http://tech.pro/tutorial/1527/matrix-multiplication-in-functional-javascriptit works like charm. Example (You can print a matrix with style in Chrome and Firefox console with console.table() ):
您可以使用来自:http: //tech.pro/tutorial/1527/matrix-multiplication-in-functional-javascript的multiplyMatrices() 函数,它的作用就像魅力一样。示例(您可以使用 console.table() 在 Chrome 和 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 */


回答by user3580838
If you wanted to go the bonkers route, you could also possibly do something with the vertices transformation in WebGL facilities now available in some modern browsers.
如果你想走疯子路线,你也可以用 WebGL 工具中的顶点转换做一些事情,这些工具现在在一些现代浏览器中可用。
Not really sure if this would work in the same way as one might approach vector transformation in OpenCL (**in fact they're type-equivalent / interoperable), but the general idea is:
不确定这是否会像在 OpenCL 中处理向量转换一样工作(**实际上它们是类型等效的/可互操作的),但总体思路是:
adding your values to a buffer
"pretending" it's an array of vertices
transforming en-mass using the GPU engine
retrieving the revised values from the vector
将您的值添加到缓冲区
“假装”它是一个顶点数组
使用 GPU 引擎转换整体
从向量中检索修改后的值
(see demo here) http://www.html5rocks.com/en/tutorials/webgl/webgl_transforms/
(请参阅此处的演示) http://www.html5rocks.com/en/tutorials/webgl/webgl_transforms/
Just an alternative to the usual loop-in-loop approach. And to be honest, a bit of a fiddle, given that OpenCL was designed for this kind of thing
只是通常的循环中循环方法的替代方法。老实说,考虑到 OpenCL 是为这种事情而设计的,这有点麻烦
Within the OpenCL 1.2 spec vertex buffers from OpenGL can be loaded and transformed using OpenCL (see. https://software.intel.com/en-us/articles/opencl-and-opengl-interoperability-tutorial)
在 OpenCL 1.2 规范中,可以使用 OpenCL 加载和转换来自 OpenGL 的顶点缓冲区(参见。https://software.intel.com/en-us/articles/opencl-and-opengl-interoperability-tutorial)
回答by Jan Turoň
For those interested in pure functional solution:
对于那些对纯函数式解决方案感兴趣的人:
let MatrixProd = (A, B) =>
A.map((row, i) =>
B[0].map((_, j) =>
row.reduce((acc, _, n) =>
acc + A[i][n] * B[n][j], 0
)
)
)
Testing code for your browser:
浏览器测试代码:
let A = [[8, 3], [2, 4], [3, 6]];
let B = [[1, 2, 3], [4, 6, 8]];
console.table(MatrixProd(A,B));
回答by Shumi Gupta
You can solve this problem with dynamic programmingusing Memoization. It is a term describing an optimization technique where you cache previously computed results, and return the cached result when the same computation is needed again.
您可以通过使用Memoization 的动态编程来解决这个问题。这是一个描述优化技术的术语,您可以缓存先前计算的结果,并在再次需要相同的计算时返回缓存的结果。
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);
For the above input value of saveComputationwill be
对于上面的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 }
回答by Alex Chebotarsky
Here's my ES6 soulution with math error handling:
这是我的带有数学错误处理的 ES6 解决方案:
const matrixDot = (A, B) => {
// Math error handling
const matrices = [A, B];
const cols = matrices.map((item) => item[0].length);
if (!matrices.every((item, i) => item.every((row) => row.length === cols[i]))) {
return console.error('All rows in a matrix must have equal amount of columns');
} else if (cols[0] !== B.length) {
return console.error(
'Amount of columns of the 1st matrix must be equal to amount of rows of the 2nd matrix'
);
}
// Calculations
return A.map((rowA) =>
B[0].map((item, colBIndex) =>
rowA.reduce((acc, itemA, rowBIndex) => acc + itemA * B[rowBIndex][colBIndex], 0)
)
);
};
// Testing
const matrix1 = [
[3, 4],
[7, 2],
[5, 9],
]; //3 x 2
const matrix2 = [
[3, 1, 5],
[6, 9, 7],
]; // 2 x 3
console.log(matrixDot(matrix1, matrix2));
Here's gistif you want to bookmark it
如果你想给它添加书签,这是要点
Hope it helps somebody ;)
希望它可以帮助某人;)
回答by EDdy
npm install express
node server.js
npm 安装快递
节点服务器.js
var express = require('express');
var app = express();
var A=new Array(3);
var B=new Array(3);
var preA = [ 1, 2, 3, 4, 5, 6,7, 8, 9 ];
var preB = [ 1,1 ,1,2,2, 2,3, 3, 3 ];
//#########################preparing blank 3*3 matrix A and B###############
for(i=0;i<3;i++){
A[i]=new Array(3);
B[i]=new Array(3);
}
//#####################Assigning values to matrix places from predefine arrays preA and preB #####
var k=0;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
A[i][j]=preA[k];
B[i][j]=preB[k];
k++;
}
};
console.log('################################');
console.log('First matrix:');
console.log(A[0]);
console.log(A[1]);
console.log(A[2]);
console.log('');
console.log('################################');
console.log('Second matrix:');
console.log(B[0]);
console.log(B[1]);
console.log(B[2]);
//###################### multiplication logic as disscussed ################
var result =[];
for (var i = 0; i < 3; i++) {
result[i] = new Array(3);
for (var j = 0; j < 3; j++) {
var sum = 0;
for (var k = 0; k < 3; k++) {
sum += A[i][k] * B[k][j];
}
result[i][j] = sum;
}
}
console.log('');
console.log('################################');
console.log('################################');
console.log('After Multiplication');
console.log(result[0]);
console.log(result[1]);
console.log(result[2]);
app.listen(9999);

