Je fais une fonction qui multiplie 2 matrices. Les matrices auront toujours le même nombre de lignes et de colonnes. (2x2, 5x5, 23x23, ...)
Lorsque je l'imprime, cela ne fonctionne pas. Pourquoi?
Par exemple, si je crée deux matrices 2x2:
matriceA:
[1][2]
[3][4]
matriceB:
[5][6]
[7][8]
Le résultat devrait être:
[19][22]
[43][50]
( http://ncalculators.com/matrix/2x2-matrix-multiplication-calculator.htm )
Mais je reçois:
[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
Vous vous confondez avec vos différents tableaux temporaires. Les valeurs undefined
sont provoquées par un accès hors limites sur la ligne sous votre boucle la plus intérieure.
Je vous recommande de vous en tenir à faire un seul tableau pour le résultat de la multiplication. Comme vous le savez probablement, le problème est que JavaScript ne vous permet pas d'initialiser un tableau multidimensionnel. Pour créer un tableau bidimensionnel, vous devez initialiser un tableau unidimensionnel, puis parcourir ses éléments et initialiser chacun en un tableau unidimensionnel.
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));
Vous pouvez utiliser la fonction multiplyMatrices () à partir de: http://tech.pro/tutorial/1527/matrix-multiplication-in-functional-javascript cela fonctionne comme un charme. Exemple (Vous pouvez imprimer une matrice avec style dans Chrome et console Firefox avec console.table ()):
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 */
Je sais que c'est une vieille question mais je recommande pour passer à ma réponse.
Ma solution a de bonnes performances car elle utilise les fonctions
Map
Reduce
//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));
Si vous vouliez emprunter la voie bonkers, vous pourriez également faire quelque chose avec la transformation des sommets dans les installations WebGL maintenant disponible dans certains navigateurs modernes.
Je ne sais pas vraiment si cela fonctionnerait de la même manière que l'on pourrait aborder la transformation vectorielle dans OpenCL (** en fait, ils sont de type équivalent/interopérables), mais l'idée générale est:
ajouter vos valeurs à un tampon
"faire semblant" c'est un tableau de sommets
transformation en masse à l'aide du moteur GPU
récupérer les valeurs révisées du vecteur
(voir la démo ici) http://www.html5rocks.com/en/tutorials/webgl/webgl_transforms/
Juste une alternative à l'approche habituelle en boucle. Et pour être honnête, un peu un violon, étant donné que OpenCL a été conçu pour ce genre de chose
Dans la spécification OpenCL 1.2, les tampons de vertex d'OpenGL peuvent être chargés et transformés à l'aide d'OpenCL (voir. https://software.intel.com/en-us/articles/opencl-and-opengl-interoperability-tutorial =)
Vous pouvez résoudre ce problème avec programmation dynamique en utilisant mémorisation. Il s'agit d'un terme décrivant une technique d'optimisation dans laquelle vous mettez en cache les résultats précédemment calculés et renvoyez le résultat mis en cache lorsque le même calcul est à nouveau nécessaire.
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);
Pour la valeur d'entrée ci-dessus de saveComputation sera
{ '1*1': 1,
'2*1': 2,
'1*2': 2,
'3*1': 3,
'1*3': 3,
'2*2': 4,
'3*2': 6,
'2*3': 6 }