237 votos

¿Cuáles son las diferencias entre una matriz multidimensional y una matriz de matrices en C#?

¿Cuáles son las diferencias entre matrices multidimensionales double[,] matriz de matrices y double[][] en C#?

Si hay una diferencia, ¿cuál es el mejor uso para cada uno.

173voto

Dmitriy Matveev Puntos 4680

Array de arrays (matrices escalonadas) son más rápidas que las matrices multidimensionales y pueden ser utilizados más efectivamente. Matrices multidimensionales tienen más agradable de sintaxis.

Si escribes un código simple de usar irregulares y matrices multidimensionales y, a continuación, inspeccione el ensamblado compilado con un IL desensamblador verá que el almacenamiento y la recuperación de irregulares (o unidimensional) las matrices son simples IL instrucciones, mientras que el mismo las operaciones de matrices multidimensionales son invocaciones de métodos que son siempre más lenta.

Considere los siguientes métodos:

static void SetElementAt(int[][] array, int i, int j, int value)
{
    array[i][j] = value;
}

static void SetElementAt(int[,] array, int i, int j, int value)
{
    array[i, j] = value;
}

Su IL será el siguiente:

.method private hidebysig static void  SetElementAt(int32[][] 'array',
                                                    int32 i,
                                                    int32 j,
                                                    int32 'value') cil managed
{
  // Code size       7 (0x7)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  ldelem.ref
  IL_0003:  ldarg.2
  IL_0004:  ldarg.3
  IL_0005:  stelem.i4
  IL_0006:  ret
} // end of method Program::SetElementAt

.method private hidebysig static void  SetElementAt(int32[0...,0...] 'array',
                                                    int32 i,
                                                    int32 j,
                                                    int32 'value') cil managed
{
  // Code size       10 (0xa)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  ldarg.2
  IL_0003:  ldarg.3
  IL_0004:  call       instance void int32[0...,0...]::Set(int32,
                                                           int32,
                                                           int32)
  IL_0009:  ret
} // end of method Program::SetElementAt

Cuando el uso de matrices escalonadas usted puede fácilmente realizar operaciones tales como la fila de intercambio de fila y cambiar de tamaño. Tal vez en algunos casos el uso de matrices multidimensionales será más seguro, pero incluso Microsoft FxCop dice que las matrices escalonadas debe ser utilizado en lugar de multidimensional cuando se utiliza para analizar sus proyectos.

127voto

John Leidegren Puntos 21951

Una matriz multidimensional crea una agradable lineal diseño de memoria mientras una matriz escalonada implica varios niveles extra de indirección.

Buscando el valor irregulares[3][6] en una matriz escalonada var dentados = new int[10][5] como funciona: busca el elemento en el índice 3 (que es una matriz) y buscar el elemento en el índice 6 la matriz (que es un valor). Para cada dimensión, en este caso, hay un adicional de mirar hacia arriba (esto es muy caro, el acceso a la memoria del patrón).

Una matriz multidimensional está dispuesto de forma lineal en la memoria, el valor real se encuentra por junto multiplicando los índices. Sin embargo, dada la matriz de var a = new int[10,30] la Longitud de propiedad de la matriz multidimensional devuelve el número total de elementos es decir. 10 * 30 = 300.

El Rango de la propiedad de una matriz escalonada siempre es 1, pero de una matriz multidimensional puede tener cualquier valor. El método GetLength de cualquier matriz puede ser utilizado para obtener la longitud de cada dimensión. Para la matriz multidimensional en este ejemplo mult.GetLength(1) devuelve 30.

La indexación de la matriz multidimensional es más rápido por ejemplo. dada la matriz multidimensional en este ejemplo mult[1,7] = 30 * 1 + 7 = 37, obtener el elemento en el índice 37. Este es un mejor acceso a la memoria patrón porque sólo una ubicación de la memoria, que es la dirección base de la matriz.

Una matriz multidimensional, por tanto, asigna un continuo bloque de memoria, mientras que una matriz escalonada no tiene que ser cuadrado gusta. por ejemplo. jagged[1].Length no tiene que ser igual irregulares[2].Length que sería cierto para cualquier matriz multidimensional.

Rendimiento

Rendimiento de los sabios, las matrices multidimensionales debe ser más rápido. Mucho más rápido, pero debido a una mala ejecución CLR no lo son.

 23.084  16.634  15.215  15.489  14.407  13.691  14.695  14.398  14.551  14.252 
 25.782  27.484  25.711  20.844  19.607  20.349  25.861  26.214  19.677  20.171 
  5.050   5.085   6.412   5.225   5.100   5.751   6.650   5.222   6.770   5.305 

La primera fila son los tiempos de las matrices escalonadas, el segundo muestra las matrices multidimensionales y la tercera, así que es como debe ser. El programa se muestra a continuación, para su INFORMACIÓN esta fue probado ejecución mono. (El windows tiempos son muy diferentes, debido principalmente a la ejecución CLR variaciones).

En windows, los tiempos de las matrices escalonadas son enormemente superior, aproximadamente el mismo que el de mi propia interpretación de lo que la matriz multidimensional buscar como debería ser, consulte la sección " Único()'. Lamentablemente, el que windows JIT compiler es realmente estúpido, y lamentablemente, esto hace que estas conversaciones sobre el desempeño difícil, hay demasiadas incoherencias.

Estos son los horarios tengo en windows, mismo trato aquí, la primera fila son las matrices escalonadas, segundo multidimensional y la tercera de mi propia implementación de multidimensional, tenga en cuenta cuánto más lento, esto es en windows comparación con el mono.

  8.438   2.004   8.439   4.362   4.936   4.533   4.751   4.776   4.635   5.864
  7.414  13.196  11.940  11.832  11.675  11.811  11.812  12.964  11.885  11.751
 11.355  10.788  10.527  10.541  10.745  10.723  10.651  10.930  10.639  10.595

Código fuente:

using System;
using System.Diagnostics;
static class ArrayPref
{
    const string Format = "{0,7:0.000} ";
    static void Main()
    {
        Jagged();
        Multi();
        Single();
    }

    static void Jagged()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var jagged = new int[dim][][];
            for(var i = 0; i < dim; i++)
            {
                jagged[i] = new int[dim][];
                for(var j = 0; j < dim; j++)
                {
                    jagged[i][j] = new int[dim];
                    for(var k = 0; k < dim; k++)
                    {
                        jagged[i][j][k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }

    static void Multi()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var multi = new int[dim,dim,dim];
            for(var i = 0; i < dim; i++)
            {
                for(var j = 0; j < dim; j++)
                {
                    for(var k = 0; k < dim; k++)
                    {
                        multi[i,j,k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }

    static void Single()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var single = new int[dim*dim*dim];
            for(var i = 0; i < dim; i++)
            {
                for(var j = 0; j < dim; j++)
                {
                    for(var k = 0; k < dim; k++)
                    {
                        single[i*dim*dim+j*dim+k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }
}

30voto

shahkalpesh Puntos 21553

Simplemente poner las matrices multidimensionales son similares a los de una tabla en el DBMS.
Matriz de Matriz (matriz escalonada) le permite tener cada elemento de tener otra matriz del mismo tipo de longitud variable.

Por lo tanto, si usted está seguro de que la estructura de datos se parece a una tabla (fijo de filas/columnas), se puede utilizar una matriz multidimensional. Matriz escalonada se fija de elementos y cada elemento puede contener un array de longitud variable

Por ejemplo. Psuedocode:

int[,] data = new int[2,2];
data[0,0] = 1;
data[0,1] = 2;
data[1,0] = 3;
data[1,1] = 4;

Creo que de los de arriba como una tabla de 2x2:

1 | 2
3 | 4
int[][] jagged = new int[2][]; 
jagged[0] = new int[4] {  1,  2,  3,  4 }; 
jagged[1] = new int[2] { 11, 12 }; 
jagged[2] = new int[3] { 21, 22, 23 }; 

Creo que de los de arriba como cada fila habiendo número variable de columnas:

 1 |  2 |  3 | 4
11 | 12
21 | 22 | 23

7voto

abatishchev Puntos 42425

Matrices de dimensión múltiple son (n-1)-matrices de dimensión.

¿ int[,] square = new int[2,2] Es la Plaza matriz 2 x 2, int[,,] cube = new int [3,3,3] es un cubo - Plaza Matriz 3 x 3. Proporcionalidad no es necesaria.

Matrices escalonadas son sólo matriz de matrices - una matriz donde cada célula contiene una matriz.

MDA son proporcionales, JD puede no ser! Cada célula puede contiene una matriz de longitud arbitraria.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X