// CMatrix.cpp (c) 2006 adolfo@di-mare.com /** \file CMatrix.cpp \brief Ejemplo de uso de matrices bidimensionales de tamaño fijo. \author Adolfo Di Mare \date 2006 */ #include // assert() #include // printf() #include // srand() && rand() /// Define el tipo \c MatrixCON como una matriz bidimensional. /// - Las dimensiones máximas de la matriz son 21x8. /// - Abreviatura para definir int M[21][8]; typedef int MatrixCON[17][8]; /// Define el tipo \c MatrixSIN como una matriz bidimensional. /// - Esta es una matriz de 8 columnas. /// - En C y en C++ se puede omitir la primera dimensión al pasar como /// parámetro cualquier matriz. /// - En C y en C++ se puede omitir la dimensión de cualquier vector al /// pasarlo como parámetro (pues en realidad se copia el puntero). typedef int MatrixSIN[][8]; /// Muestra que al pasar como parámetro una matriz se puede omitir /// su primera dimensión. void conCON_sinSIN( const MatrixSIN SIN, const MatrixCON CON ) { using namespace std; assert( sizeof(MatrixCON) == 17*8 * sizeof(int) ); // assert( sizeof(MatrixSIN) == 17*8 * sizeof(int) ); // ERROR !!! assert( sizeof(SIN) == sizeof(CON) && sizeof(CON) != sizeof(MatrixCON)); #define NCOLS(M) ( sizeof(M [0]) / sizeof(M [0][0]) ) unsigned N_COLS = sizeof(SIN[0]) / sizeof(SIN[0][0]), N_ROWS=17; assert( N_COLS == 8 && 8 == NCOLS(SIN) && NCOLS(SIN) == NCOLS(CON)); assert( "SI es posible calcular NROWS(MatrixCON)"); { unsigned N_ROWS = sizeof(MatrixCON) / ( sizeof(CON[0][0]) * NCOLS(CON) ); assert( N_ROWS == 17 ); } assert( "NO es posible calcular NROWS(CON)" "(pues CON es un puntero)"); { assert( N_ROWS != sizeof( CON ) / ( sizeof(CON[0][0]) * NCOLS(CON) ) ); assert( 0000 == sizeof( CON ) / ( sizeof(CON[0][0]) * NCOLS(CON) ) ); } assert( sizeof(SIN) == sizeof(void*) ); // las matrices son punteros assert( sizeof(CON) == sizeof(void*) ); assert( sizeof(SIN[0]) == 8 * sizeof( SIN[0][0] ) ); assert( sizeof(CON[0]) == 8 * sizeof( CON[0][0] ) ); assert( sizeof(SIN[0][0]) == sizeof( int ) ); assert( sizeof(CON[0][0]) == sizeof( int ) ); assert( sizeof(SIN[0]) == 8 * 4 ); assert( sizeof(CON[0]) == 8 * 4 ); assert( N_ROWS == sizeof(MatrixCON) / ( sizeof(SIN[0][0]) * N_COLS ) ); assert( N_ROWS == sizeof(MatrixCON) / sizeof(SIN[0][0]) / N_COLS ); } /** Calcula la multiplicación A * B y la almacena en \c Res. - \c A es una matriz de dimensiones A_Rows x A_Cols . - \c B es una matriz de dimensiones B_Rows x B_Cols . - Las dimensiones de \c Res después de la multipliación son A_Rows x B_Cols . \pre - \c "A" y \c "B" deben tener dimensiones compatibles. - A_Cols == B_Rows . - La multiplicación se hace [Fila x Columna], lo que implica que la cantidad de valores en la columnas de \c "A" debe ser igual a la cantidad de filas de \c "B". \par Complejidad: O( A_Cols * B_Cols * A_Cols ) */ void Multiplique( int Res[][8], // sin el "typedef" const MatrixSIN A, unsigned A_Rows, unsigned A_Cols, const MatrixSIN B, unsigned B_Rows, unsigned B_Cols ) { assert( A_Cols == B_Rows ); for (unsigned i=0; i error !!! } Res[i][j] = sum; // también funciona } } return; } /// Graba en \c COUT por filas el valor de la matriz \c "M". /// - \c M es una matriz de dimensiones M_Rows x M_Cols . void Grabador( const char* name, const MatrixSIN M, unsigned M_Rows, unsigned M_Cols ) { using namespace std; printf("\n %s[%d,%d]\n", name,M_Rows,M_Cols); assert( 8 == ( sizeof( M[0] ) / sizeof( M[0][0] ) ) ) ; for (unsigned i=0; i < M_Rows; ++i) { for (unsigned j=0; j < M_Cols; ++j) { // COUT << " " << setw(3) << M[i][j]; printf( " %3d", M[i][j]); } // COUT << endl; printf( "\n"); } } /** Efectúa esta multiplicación matricial Res = A x B: \code A[3,4] B[4,5] / \ / ___ \ | 1 8 0 0 | | 0 1 | 1 | 5 0 | [1]_|_0___9___9___1_| X | 0 3 | 5 | 8 7 | | 5 6 9 6 | | 6 0 | 2 | 4 6 | \ / | 0 8 |_0_| 0 0 | \ [2] / Resultado Res[3,5] / \ 0 | 0 25 41 69 56 | ===> [1] | 54 35 63 108 117 | 2 | 54 71 53 109 96 | \ | / 0 1 [2] 3 4 Res[1][2] == 0*1 + 9*5 + 9*2 + 1*0 == 63 \endcode */ int main() { MatrixCON A,B, Res; int i,j; unsigned A_Rows = 3 , A_Cols = 4; unsigned B_Rows = 4 , B_Cols = 5; srand( 1492 ); // inicializa la semilla aleatoria for (i=0; i < A_Rows; i++) { for (j=0; j < A_Cols; j++) { A[i][j] = ( (rand()%4 > 0) ? rand() % 10 : 0 ); } // 25% de ceros en la matriz } Grabador( "A", A, A_Rows, A_Cols ); for (i=0; i < B_Rows; i++) { for (j=0; j < B_Cols; j++) { B[i][j] = ( (rand()%4 > 0) ? rand() % 10 : 0 ); } // 25% de ceros en la matriz } Grabador( "B", B, B_Rows, B_Cols ); Multiplique( Res, A, A_Rows, A_Cols, B, B_Rows, B_Cols ); Grabador( "Resultado Res", Res, A_Rows, B_Cols ); conCON_sinSIN( A,A ); return 0; } // EOF: CMatrix.cpp