it-swarm.com.de

array-Offset-Berechnungen in mehrdimensionalen Arrays (Spalte vs. Zeilenhaupt)

Ein Lehrbuch, das ich kürzlich gelesen habe, besprach Zeilenreihen- und Spaltenhauptarrays. Das Buch konzentrierte sich hauptsächlich auf 1- und 2-dimensionale Arrays, diskutierte aber nicht wirklich 3-dimensionale Arrays. Ich bin auf der Suche nach guten Beispielen, um mein Verständnis der Adressierung eines Elements innerhalb eines mehrdimensionalen Arrays mithilfe von Row-Major- und Column-Major-Arrays zu festigen.

 + - + - + - + | 
//// | 
 + - + - + - + + | + --- + --- + --- + --- + 
//// |/| |//// /| ± .____.] + - + - + - + + + | + --- + --- + --- + --- + + 
//// |/|/| |//// /|/|
 + - + - + - + + + + | + --- + --- + --- + --- + + + 
//// |/|/|/| |//// /|/|/|
 + - + - + - + + + + + | + --- + --- + --- + --- + + + 
//// |/|/|/|/| | 000 | 001 | 002 | 003 |/|/|/| 
 + - + - + + + + + + | + --- + --- + --- + --- + + + 
 | 00 | 01 | 02 |/|/|/|/| | 004 | 005 | 006 | 007 |/|/|/| 
 + - + - + + + + + | + --- + --- + --- + --- + + + 
 | 03 | 04 | 05 |/|/|/| | 008 | 009 | 00A | 00B |/|/| /
 + - + - + - + + | | + --- + --- + --- + --- + + + 
 | 06 | 07 | 08 |/|/| | 00C | 00D | 00E | 00F |/| /
 + - + - + - + + | + --- + --- + --- + --- + + 
 | 09 | 0A | 0B |/| | 010 | 011 | 012 | 013 | /
 + - + - + - + | + --- + --- + --- + --- + 
 arr [5] [3] [4] | arr [3] [4] [5] 

HINWEIS: Originalfrage falsch dargestellt arr [3] [4] [5]. Ich habe gelernt, dass der ursprüngliche Index Tiefe darstellt. Die Daten wurden korrigiert, um die beabsichtigte Array-Darstellung wiederzugeben.

 Beispiel für Hexadezimaldaten 
 + --- + --- + --- + --- + --- + --- + --- + --- + --- + + - - + --- + --- + --- + 
 | 000 | 001 | 002 | 003 | | 100 | 101 | 102 | 103 | | 200 | 201 | 202 | 203 | 
 + --- + --- + --- + + + --- + --- + --- + --- + + --- + --- + --- + - - + --- + 
 | 004 | 005 | 006 | 007 | | 104 | 105 | 106 | 107 | | 204 | 205 | 206 | 207 | 
 + --- + --- + --- + + + --- + --- + --- + --- + + --- + --- + --- + - - + --- + 
 | 008 | 009 | 00A | 00B | | 108 | 109 | 10A | 10B | | 208 | 209 | 20A | 20B | 
 + --- + --- + --- + + + --- + --- + --- + --- + + --- + --- + --- + - - + --- + 
 | 00C | 00D | 00E | 00F | | 10C | 10D | 10E | 10F | | 20C | 20D | 20E | 20F | 
 + --- + --- + --- + --- + + --- + --- + --- + --- + --- + + - - + --- + --- + --- + 
 | 010 | 011 | 012 | 013 | | 110 | 111 | 112 | 113 | | 210 | 211 | 212 | 213 | 
 + --- + --- + --- + --- + + --- + --- + --- + --- + --- + + - - + --- + --- + --- + 
 Scheibe 0 Scheibe 1 Scheibe 2 
 
 kurze Arr. [3] [4] [5]; // Angenommen, das Array ist mit Hex-Testdaten gefüllt. 
 
 arr [1] [2] [3] = 0x10B Verwenden Sie Slice 1, Zeile 2, Spalte 3 
 arr [2]. [3] [4] = 0x210 Verwende Slice 2, Zeile 3, Spalte 4 
 In Zeile 4, Spalte 0 
 
.

reihenmajor
{000,001,002,003,004,004,005,006,007,008,009,00A, 00B, 00C, 00D, 00E, 00F, 010,011,012,013, ein Mitlauf, ein Mitlauf, ein Mitlauf, ein Mitlauf, ein Mitlauf, ein Mitlauf, ein Durchbruch, ein Durchbruch, ein Durchbruch, ein Mit 20A, 20B, 20C, 20D, 20E, 20F, 210,211,212,213}

kolonne Dur {000.004.008,00C, 010.001.005,009,00D, 011.002,006,00A, 00E, 012.003,007,00B, 00F, 013, 100,104,108,10C, 110,101,105,109,10D, 111,102,106,10A, 10E, 112,103,107 10B, 10F, 113, 200,204,208,20C, 210,201,205,209,20D, 211,202,206,20A, 20E, 212,203,207,20B, 20F, 213}

 Berechnungsoffset für arr [1] [2] [3] unter Verwendung des Zeilenhauptversatzes? 
 Berechnungsoffset für arr [1] [2] [3] unter Verwendung des Spaltenhauptversatzes? 
24
mrwes

Als ich diese Frage stellte, hoffte ich auf gute dreidimensionale Array-Beispiele. Insbesondere Codebeispiele. Da ich nichts Verständliches fand, entschied ich mich, ein kleines C-Programm zu erstellen, um das Konzept besser darstellen zu können. Es verwendet die gleichen Testdaten in einem 3x4x5-Array. Es enthält auch Testdaten für ein 5x5x5-Array. Es erstellt ein Spaltenhauptfeld aus dem Zeilenhauptfeld, so dass die Versatzberechnungen überprüft werden können.

Die Array-Offset-Methoden sind:

  • char * calc_RowMajor (char * Basis, int elemSz, int depth_idx, int row_idx, int col_idx)
  • char * calc_ColMajor (char * Basis, int elemSz, int depth_idx, int col_idx, int row_idx)

    Ich habe ggf. Kommentare in den Code eingefügt, um zu klären, was der Code tut.

    
    //
    // Arrays.cpp : 
    //     Purpose: Display rowMajor & colMajor data and calculations.
    //
    #include "stdafx.h"
    
    #define _show_Arrays 1  // 1=display rowMajor & colMajor arrays
    #define _square_array 0 // 1=use arr[5][5][5], 0=use arr[3][4][5]
    
    #if (_square_array == 1)
        const int depthSz = 5;
        const int rowSz = 5;
        const int colSz = 5;
        /*
        +---+---+---+---+---+
        |x00|x01|x02|x03|x04|
        +---+---+---+---+---+ 
        |x05|x06|x07|x08|x09|   
        +---+---+---+---+---+  
        |x0A|x0B|x0C|x0D|x0E|   
        +---+---+---+---+---+   
        |x0F|x10|x11|x12|x13|
        +---+---+---+---+---+ 
        |x14|x15|x16|x17|x18|
        +---+---+---+---+---+ 
              slice x          
        */
        short row_arr[depthSz][colSz][rowSz] = {
        { /* slice 0 */
          {0x000,0x001,0x002,0x003,0x004},
          {0x005,0x006,0x007,0x008,0x009},
          {0x00A,0x00B,0x00C,0x00D,0x00E},
          {0x00F,0x010,0x011,0x012,0x013},
          {0x014,0x015,0x016,0x017,0x018}},
        { /* slice 1 */
          {0x100,0x101,0x102,0x103,0x104},
          {0x105,0x106,0x107,0x108,0x109},
          {0x10A,0x10B,0x10C,0x10D,0x10E},
          {0x10F,0x110,0x111,0x112,0x113},
          {0x114,0x115,0x116,0x117,0x118}},
        { /* slice 2 */
          {0x200,0x201,0x202,0x203,0x204},
          {0x205,0x206,0x207,0x208,0x209},
          {0x20A,0x20B,0x20C,0x20D,0x20E},
          {0x20F,0x210,0x211,0x212,0x213},
          {0x214,0x215,0x216,0x217,0x218}},
        { /* slice 3 */
          {0x300,0x301,0x302,0x303,0x304},
          {0x305,0x306,0x307,0x308,0x309},
          {0x30A,0x30B,0x30C,0x30D,0x30E},
          {0x30F,0x310,0x311,0x312,0x313},
          {0x314,0x315,0x316,0x317,0x318}},
        { /* slice 4 */
          {0x400,0x401,0x402,0x403,0x404},
          {0x405,0x406,0x407,0x408,0x409},
          {0x40A,0x40B,0x40C,0x40D,0x40E},
          {0x40F,0x410,0x411,0x412,0x413},
          {0x414,0x415,0x416,0x417,0x418}}
        };
    
    #else
      const int depthSz = 3;
        const int rowSz = 4;
        const int colSz = 5;
        /*
        +---+---+---+---+
        |000|001|002|003|  
        +---+---+---+---+  
        |004|005|006|007|   
        +---+---+---+---+   
        |008|009|00A|00B|   
        +---+---+---+---+   
        |00C|00D|00E|00F|
        +---+---+---+---+ 
        |010|011|012|013|
        +---+---+---+---+ 
             slice x
        */
        short row_arr[depthSz][colSz][rowSz] = {
        {  /* slice 0 */
          {0x000,0x001,0x002,0x003},
          {0x004,0x005,0x006,0x007},
          {0x008,0x009,0x00A,0x00B},
          {0x00C,0x00D,0x00E,0x00F},
          {0x010,0x011,0x012,0x013}},
        { /* slice 1 */
          {0x100,0x101,0x102,0x103},
          {0x104,0x105,0x106,0x107},
          {0x108,0x109,0x10A,0x10B},
          {0x10C,0x10D,0x10E,0x10F},
          {0x110,0x111,0x112,0x113}},
        {  /* slice 2 */
          {0x200,0x201,0x202,0x203},
          {0x204,0x205,0x206,0x207},
          {0x208,0x209,0x20A,0x20B},
          {0x20C,0x20D,0x20E,0x20F},
          {0x210,0x211,0x212,0x213}}
        };
    #endif
        short col_arr[depthSz*colSz*rowSz]; //
    
    char *calc_RowMajor(char *Base, int elemSz, int depth_idx, int row_idx, int col_idx)
    {  // row major slice is navigated by rows
      char *address;
      int   lbound = 0; // lower bound (0 for zero-based arrays)
      address = Base        /* use base passed */
         + ((depth_idx-lbound)*(colSz*rowSz*elemSz))    /* select slice */
         + ((row_idx-lbound)*rowSz*elemSz)      /* select row */
         + ((col_idx-lbound)*elemSz);       /* select col */
        return address;
    }
    char *calc_ColMajor(char *Base, int elemSz, int depth_idx, int col_idx, int row_idx)
    {  // col major slice is navigated by columns
      char *address;
      int   lbound = 0; // lower bound (0 for zero-based arrays)
      int   pageSz = colSz*rowSz*elemSz; 
      int   offset;
    
      offset = (col_idx-lbound)*(colSz*elemSz)  /* select column */
             + (row_idx-lbound)*(elemSz);   /* select row */
        if (offset >= pageSz)
        {   // page overflow, rollover
            offset -= (pageSz-elemSz);                          /* ajdust offset back onto page */
        }
        address = Base            /* use base passed */
                + ((depth_idx-lbound)*pageSz)  /* select slice */
                + offset;
        return address;
    }
    
    void disp_slice(char *pStr, short *pArr,int slice,int cols, int rows)
    {
      printf("== %s slice %d == %p\r\n",pStr, slice,pArr+(slice*rows*cols));
      for(int x=0;x<rows;x++)
      {
        for(int y=0;y<cols;y++)
          printf("%03X ",*(pArr+(slice*rows*cols)+(x*cols)+y));
          printf("\r\n");
      }
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      // initialize col based array using row based array data
      { // convert row_arr into col_arr
        short *pSrc = &row_arr[0][0][0];
        short *pDst = &col_arr[0];
        for(int d=0;d<depthSz;d++)
          for(int r=0;r<rowSz;r++)
            for(int c=0;c<colSz;c++)
            {
        *pDst++ = *(pSrc+((d*rowSz*colSz)+(c*rowSz)+r));
            }
      }
    
      printf("Using Array[%d][%d][%d]\r\n",depthSz,rowSz,colSz);
    
    #if (_show_Arrays == 1)
      { for(int x=0;x<depthSz;x++) {disp_slice("rowMajor",&row_arr[0][0][0],x,rowSz,colSz);}}
      { for(int x=0;x<depthSz;x++) {disp_slice("colMajor",&col_arr[0],x,rowSz,colSz);}}
    #endif
    
      int d = 2;    // depth
      int r = 3;    // row
      int c = 4;    // column
    
      for(d=0;d<depthSz;d++)
      { 
        c = r = d;  // simple access test pattern arr[0][0][0],arr[1][1][1],arr[2][2][2],...
        { // retrieve Array element
          printf("    row_arr[%d][%d][%d] = %x\t",d,r,c,row_arr[d][r][c]);
          printf("&row_arr[%d][%d][%d] = %p\r\n",d,r,c,&row_arr[d][r][c]);
        }
        { // retrieve RowMajor element
          short *pRowMajor = (short*)calc_RowMajor((char*)&row_arr[0][0][0],sizeof(short),d,r,c);
          printf("calc_RowMajor(%d,%d,%d) = %x\t\t",d,r,c,*pRowMajor);
          printf("pRowMajor = %p\r\n",pRowMajor);
        }
        {   // retrieve ColMajor element
          short *pColMajor = (short*)calc_ColMajor((char*)&col_arr[0],sizeof(short),d,c,r);
          printf("calc_ColMajor(%d,%d,%d) = %x\t\t",d,r,c,*pColMajor);
          printf("pColMajor = %p\r\n",pColMajor);
        }
     } // for
    
     getchar(); // just to hold the console while looking at the information
      return 0;
    }
    
  • 0
    mrwes

    Beschränken Sie sich nicht künstlich, indem Sie sich auf 3-dimensional und 2-dimensional konzentrieren. Stattdessen Fokus auf das Erlernen des Ausdrucks zum Adressieren von n-dimensionalen Arrays

    Das Ausdrücken einer n-dimensionalen Adressierung würde Ihr Verständnis für dieses Thema festigen und sich leichter an eine Formel als an separate Formeln für die 2D- und 3D-Adressierung erinnern.


    Hier ist mein Versuch der n-dimensionalen Adressierung:

    #define LEN 10
    
    int getValue_nDimensions( int * baseAddress, int * indexes, int nDimensions ) {
        int i;
        int offset = 0;
        for( i = 0; i < nDimensions; i++ ) {
            offset += pow(LEN,i) * indexes[nDimensions - (i + 1)];
        }
    
        return *(baseAddress + offset);
    }
    
    int main() {
        int i;
        int * baseAddress;
        int val1;
        int val2;
    
        // 1 dimensions
        int array1d[LEN];
        int array1d_indexes[] = {2};
        int array1d_nDimensions = 1;
        baseAddress = &array1d[0];
        for(i = 0; i < LEN; i++) { baseAddress[i] = i; }
        val1 = array1d[2];
        val2 = getValue_nDimensions( // Equivalent to: val1 = array1d[2];
            baseAddress,
            &array1d_indexes[0],
            array1d_nDimensions
        );
        printf("SANITY CHECK: %d %d\n",val1,val2);
    
        // 3 dimensions
        int array3d[LEN][LEN][LEN];
        int array3d_indexes[] = {2,3,4};
        int array3d_nDimensions = 3;
        baseAddress = &array3d[0][0][0];
        for(i = 0; i < LEN*LEN*LEN; i++) { baseAddress[i] = i; }
        val1 = array3d[2][3][4];
        val2 = getValue_nDimensions( // Equivalent to: val1 = array3d[2][3][4];
            baseAddress,
            &array3d_indexes[0],
            array3d_nDimensions
        );
        printf("SANITY CHECK: %d %d\n",val1,val2);
    
        // 5 dimensions
        int array5d[LEN][LEN][LEN][LEN][LEN];
        int array5d_indexes[] = {2,3,4,5,6};
        int array5d_nDimensions = 5;
        baseAddress = &array5d[0][0][0][0][0];
        for(i = 0; i < LEN*LEN*LEN*LEN*LEN; i++) { baseAddress[i] = i; }
        val1 = array5d[2][3][4][5][6];
        val2 = getValue_nDimensions( // Equivalent to: val1 = array5d[2][3][4][5][6];
            baseAddress,
            &array5d_indexes[0],
            array5d_nDimensions
        );
        printf("SANITY CHECK: %d %d\n",val1,val2);
    
        return 0;
    }
    

    Ausgabe:

    SANITY CHECK:     2     2
    SANITY CHECK:   234   234
    SANITY CHECK: 23456 23456
    
    10

    Ich würde den Row-Major-Order Wikipedia-Artikel sehen. Es gibt einen Abschnitt, der Dimensionen größer als 2 beschreibt. Es gibt auch einen guten Artikel hier . In diesem Artikel wird die folgende Formel für ein dreidimensionales Array mit einem Zeilenhauptlayout angegeben:

    Address = Base + ((depthindex*col_size+colindex) * row_size + rowindex) * Element_Size
    

    Für ein 3D-Array: Geben Sie A [Tiefe] [Spalte] [Zeile] ein. Die Basis ist der Startversatz des Arrays. Darüber hinaus sind die Größenvariablen die unterschiedlichen Größen jeder Dimension. Die Element_Size-Variable gibt die Größe des Typs an, aus dem das Array besteht.

    Angenommen, Sie hatten ein Zeilenmajorarray a [4] [6] [5], das aus Standard-C++ - Ganzzahlen besteht. Um den Versatz von a 1 [3] 2 zu berechnen, fügen Sie die folgenden Zahlen in die Formel ein:

    Address = Base + ((1 * 6 + 3) * 5 + 2) * 4
    

    Für ein 3-dimensionales Array, das ein Spalten-Haupt-Layout hat, würde die Gleichung eher die folgende sein:

    Address = Base + ((rowindex*col_size+colindex) * depth_size + depthindex) * Element_Size
    

    Die Zahlen, die Sie in das obige Beispiel mit einem Spalten-Major-Layout einfügen würden, lauten nun wie folgt:

    Address = Base + ((2 * 6 + 3) * 4 + 1) * 4
    
    10
    Cory Walker

    Die Ausdrücke "Reihenmajor" und "Spaltenmajor" übersetzen nicht gut in eine dritte Dimension. Die Vorstellung, dass das nächste gespeicherte Element aus der aktuellen Zeile oder der aktuellen Spalte stammt, bricht zusammen. Es hört sich ein bisschen komisch an, aber dies wird zu einer Reihenfolge zwischen 'deep major' und 'width major'. Jedes nachfolgende Element ist nicht mehr ein einzelner Eintrag, sondern eine vollständige zweidimensionale Matrix.

    /X 
    /
     + --- + --- + --- + 
    //// 
     + --- + --- + --- + - + ------- 
     | 1 | 5 | 9 |/| Y 
     + --- + --- + --- + + 
     | 2 | 6 | A |/| 
     + --- + --- + --- + + 
     | 3 | 7 | B |/| 
     + --- + --- + --- + + 
     | 4 | 8 | C | /
     + --- + --- + --- + 
     
    

    Der Speicher würde also buchstäblich 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 im Speicher sequentiell haben. Dies ist die klassische Reihenfolge der Spalten. Durch das Platzieren des D-Eintrags an der mit X markierten Position haben Sie die Tatsache nicht geändert, dass Ihre Matrix die Reihenfolge der Colum-Dur hat. Wenn Sie den D-Eintrag an der Stelle des Ys platzieren, haben Sie immer noch nicht die Tatsache geändert, dass Sie die Spaltenreihenfolge verwenden. Wo Sie den nächsten Block platzieren möchten, wirkt sich auf die Reihenfolge der Tiefen (X) oder Breite (Y) aus. Wie Sie wissen, sind dies Äquivalente, aber wenn Sie es als etwas bezeichnen, kann dies beim Schreiben von Gleichungen helfen:

    [0 basierte Arrays angenommen]  

    Sie greifen auf den Speicherplatz eines zweidimensionalen Colum-Hauptelements über die Gleichung zu: 

    MatrixOffset = base + (sizeof(entry) * ((4 * ( column - 1 ))   +  (row - 1)))
    

    Diese Adresse wird mit der Tiefe oder Breite angepasst. Dies ist eine Frage der Terminologie.

    TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (depth - 1))) 
    

    ODER

    TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (width - 1))) 
    

    Die Konstanten 4 und 3 wären wahrscheinlich die Variablen COLUMNS und ROWS.

    Fragen Sie mich nicht nach der 4. Dimention!

    2
    ojblass

    Grundsätzlich wird in einem 3D-Arrray mit dem Zeilenhaupt Eg Eg Arr [3] [4] [5] Wenn u Arr [0] will, sucht es nach dem vorderen Schnitt des Bildes wie oben Arr [ 1] zweite Scheibe usw. So bedeutet Arr [0] ein 2D-Array der Größe [4] [5], daher entspricht jedes Arr [x] x * (4 * 5) Nun zu Arr [x] [y] kann man sich ein 1D-Array der Größe [5] vorstellen, dessen Position [x] [y] von oben im Bild über Ist. Wenn also Arr [x ] [y] = x * (4 * 5) + y * (5) jetzt Arr [x] [y] [z] ist das spezifische Element von Arr [x] [y] in der Tiefe z Arr [x] [y] [z] = x * (4 * 5) + y * 5 + z Jetzt auf der Grundlage der Größe des Datentyps, den u im Array speichern möchte Der Offset kann mit der Größe multipliziert werden, um die Adresse in Bezug auf Start zu erhalten

    0
    bajrangbali

    Die Formel für k-dimensionale Arrays lautet

        k-1       n
    i  + ∑  i  *  ∏  c
     0  n=1  n   m=0  m
    

    wobei i Index n der Index der Dimension n für n = {0, 1, 2, ... k-1} ist und c Index m die Kardinalität von Dimension m für m = {0, 1 ist, 2, ... k-2}.

    Eine schönere Darstellung der Formel im PNG-Format finden Sie hier:

    http://modula-2.info/m2r10/pmwiki.php/Spec/LanguageReport#MultiDimensionalArrays

    0
    trijezdci