una suma programacion matriz matrices llenar ingresar imprimir ejercicios ejemplos datos como codigo caracteres c arrays multidimensional-array zero memset

suma - matriz en c++ codigo



¿La forma más rápida de poner a cero una matriz de 2d en C? (12)

¿Cómo se declaró su matriz en 2D?

Si es algo como:

int arr[20][30];

Puedes ponerlo en cero haciendo:

memset(arr, sizeof(int)*20*30);

Quiero poner en cero varias veces una gran matriz 2D en C. Esto es lo que hago en este momento:

// Array of size n * m, where n may not equal m for(j = 0; j < n; j++) { for(i = 0; i < m; i++) { array[i][j] = 0; } }

He intentado usar memset:

memset(array, 0, sizeof(array))

Pero esto solo funciona para matrices 1D. Cuando imprimo el contenido de la matriz 2D, la primera fila es cero, pero luego recibí una gran cantidad de números aleatorios y se bloquea.


Bueno, la forma más rápida de hacerlo es no hacerlo en absoluto.

Suena extraño, sé, aquí hay un pseudocódigo:

int array [][]; bool array_is_empty; void ClearArray () { array_is_empty = true; } int ReadValue (int x, int y) { return array_is_empty ? 0 : array [x][y]; } void SetValue (int x, int y, int value) { if (array_is_empty) { memset (array, 0, number of byte the array uses); array_is_empty = false; } array [x][y] = value; }

En realidad, todavía está borrando la matriz, pero solo cuando algo se está escribiendo en la matriz. Esto no es una gran ventaja aquí. Sin embargo, si la matriz 2D se implementó usando, por ejemplo, un árbol cuádruple (no una mente dinámica), o una colección de filas de datos, entonces puede localizar el efecto de la bandera booleana, pero necesitaría más banderas. En el árbol cuádruple, simplemente configure el indicador vacío para el nodo raíz, en el conjunto de filas solo establezca el indicador para cada fila.

Lo que lleva a la pregunta "¿por qué quieres poner en cero varias veces una gran matriz 2d"? ¿Para qué se usa la matriz? ¿Hay alguna manera de cambiar el código para que la matriz no necesite puesta a cero?

Por ejemplo, si tuvieras:

clear array for each set of data for each element in data set array += element

es decir, úselo para un búfer de acumulación, luego cambiarlo de esta manera mejoraría el rendimiento sin fin:

for set 0 and set 1 for each element in each set array = element1 + element2 for remaining data sets for each element in data set array += element

Esto no requiere que la matriz se borre, pero aún funciona. Y eso será mucho más rápido que borrar la matriz. Como dije, la manera más rápida es no hacerlo en primer lugar.


Creo que la forma más rápida de hacerlo a mano es siguiendo el código. Puede comparar su velocidad con la función memset, pero no debería ser más lenta.

(cambie el tipo de punteros ptr y ptr1 si su tipo de matriz es diferente, entonces int)

#define SIZE_X 100 #define SIZE_Y 100 int *ptr, *ptr1; ptr = &array[0][0]; ptr1 = ptr + SIZE_X*SIZE_Y*sizeof(array[0][0]);

while(ptr < ptr1) { *ptr++ = 0; }


Esto sucede porque sizeof (array) te da el tamaño de asignación del objeto al que apunta array . (el conjunto es solo un puntero a la primera fila de su matriz multidimensional). Sin embargo, asignó j matrices de tamaño i . En consecuencia, debe multiplicar el tamaño de una fila, que se devuelve mediante sizeof (matriz) con el número de filas que asignó, por ejemplo:

bzero(array, sizeof(array) * j);

También tenga en cuenta que sizeof (array) solo funcionará para arrays asignados estáticamente. Para una matriz dinámicamente asignada escribirías

size_t arrayByteSize = sizeof(int) * i * j; int *array = malloc(array2dByteSite); bzero(array, arrayByteSize);


Puedes intentar esto

int array[20,30] = {{0}};


Si inicializa la matriz con malloc , use calloc ; pondrá a cero tu matriz de forma gratuita. (La misma ejecución obviamente como memset, solo menos código para ti).


Si la array es realmente una matriz, entonces puedes "ponerla a cero" con:

memset(array, 0, sizeof array);

Pero hay dos puntos que debes saber:

  • esto funciona solo si array es realmente una "matriz de dos d", es decir, se declaró T array[M][N]; para algunos tipo T
  • solo funciona en el ámbito donde se ha declarado el conjunto. Si lo pasa a una función, el array nombres se desintegrará a un puntero , y sizeof no le dará el tamaño de la matriz.

Hagamos un experimento:

#include <stdio.h> void f(int (*arr)[5]) { printf("f: sizeof arr: %zu/n", sizeof arr); printf("f: sizeof arr[0]: %zu/n", sizeof arr[0]); printf("f: sizeof arr[0][0]: %zu/n", sizeof arr[0][0]); } int main(void) { int arr[10][5]; printf("main: sizeof arr: %zu/n", sizeof arr); printf("main: sizeof arr[0]: %zu/n", sizeof arr[0]); printf("main: sizeof arr[0][0]: %zu/n/n", sizeof arr[0][0]); f(arr); return 0; }

En mi máquina, las impresiones de arriba:

main: sizeof arr: 200 main: sizeof arr[0]: 20 main: sizeof arr[0][0]: 4 f: sizeof arr: 8 f: sizeof arr[0]: 20 f: sizeof arr[0][0]: 4

Aunque arr es una matriz, se desintegra a un puntero a su primer elemento cuando se pasa a f() , y por lo tanto los tamaños impresos en f() son "incorrectos". Además, en f() el tamaño de arr[0] es el tamaño de la matriz arr[0] , que es una "matriz [5] de int ". No es el tamaño de una int * , porque la "descomposición" solo ocurre en el primer nivel, y es por eso que debemos declarar que f() toma un puntero a una matriz del tamaño correcto.

Entonces, como dije, lo que estaba haciendo originalmente funcionará solo si se cumplen las dos condiciones anteriores. Si no, tendrá que hacer lo que otros han dicho:

memset(array, 0, m*n*sizeof array[0][0]);

Finalmente, memset() y el bucle for que publicaste no son equivalentes en sentido estricto. Podría haber (y ha habido) compiladores donde "todos los bits cero" no es igual a cero para ciertos tipos, como los punteros y los valores de coma flotante. Sin embargo, dudo que tengas que preocuparte por eso.


Si realmente estás obsesionado con la velocidad (y no tanto con la portabilidad), creo que la forma más rápida y sencilla de hacerlo sería utilizar los elementos intrínsecos del vector SIMD. por ejemplo, en las CPU Intel, podría usar estas instrucciones SSE2:

__m128i _mm_setzero_si128 (); // Create a quadword with a value of 0. void _mm_storeu_si128 (__m128i *p, __m128i a); // Write a quadword to the specified address.

Cada instrucción de tienda establecerá cuatro entradas de 32 bits a cero en un golpe.

p debe estar alineado en 16 bytes, pero esta restricción también es buena para la velocidad porque ayudará a la memoria caché. La otra restricción es que p debe apuntar a un tamaño de asignación que es un múltiplo de 16 bytes, pero esto también es genial porque nos permite desenrollar el bucle fácilmente.

Haga esto en un bucle, y desenrolle el bucle varias veces, y tendrá un inicializador rápido loco:

// Assumes int is 32-bits. const int mr = roundUpToNearestMultiple(m, 4); // This isn''t the optimal modification of m and n, but done this way here for clarity. const int nr = roundUpToNearestMultiple(n, 4); int i = 0; int array[mr][nr] __attribute__ ((aligned (16))); // GCC directive. __m128i* px = (__m128i*)array; const int incr = s >> 2; // Unroll it 4 times. const __m128i zero128 = _mm_setzero_si128(); for(i = 0; i < s; i += incr) { _mm_storeu_si128(px++, zero128); _mm_storeu_si128(px++, zero128); _mm_storeu_si128(px++, zero128); _mm_storeu_si128(px++, zero128); }

También hay una variante de _mm_storeu que puentea la caché (es decir, poner a cero la matriz no contaminará la memoria caché) lo que podría brindarle algunos beneficios de rendimiento secundario en algunas circunstancias.

Consulte aquí para referencia de SSE2: http://msdn.microsoft.com/en-us/library/kcwz153a(v=vs.80).aspx


Use calloc en lugar de malloc. calloc iniciará todos los campos a 0.

int * a = (int *) calloc (n, tamaño de (int));

// todas las celdas de a se han inicializado a 0


int array[N][M] = {0};

... al menos en GCC 4.8.


memset(array, 0, sizeof(array[0][0]) * m * n);

Donde m y n son el ancho y alto de la matriz bidimensional (en su ejemplo, tiene una matriz cuadrada bidimensional, entonces m == n ).


memset(array, 0, sizeof(int [n][n]));