2D Array Index Calculator
Convert between 2D coordinates (row, column) and the 1D flat index in row-major order. Solve for the flat index, row, column, or number of columns given any three of the four quantities.
Rows first, then columns
Row-major order (used by C, C++, Java, C#, Python's NumPy by default) stores the first row completely, then the second row, then the third, and so on. The flat index of an element is the number of elements that come before it: r full rows of C elements each, plus c elements in the current row. That is exactly r · C + c.
Cache-friendly for row scans
Because consecutive elements in a row are adjacent in memory, iterating a row of a row-major array touches consecutive addresses — the CPU prefetcher loves it. Iterating a column requires striding by C bytes per access, which misses the cache on every step. This is why the loop order for r: for c: is dramatically faster than for c: for r: on row-major arrays, even though both compute the same thing.
Column-major is the mirror
Column-major order (used by Fortran, MATLAB, and Julia, and by BLAS/LAPACK under the hood) stores columns first. Its formula is index = c · R + r, where R is the number of rows. The two orders give the same element set but different flat indices. Which one is "correct" depends entirely on the language and library you are using — the same (r, c) can have completely different indices in C and Fortran.
The inverse formula is exact
Given the flat index i and the number of columns C, you can recover the row and column exactly with integer arithmetic: row = ⌊i / C⌋ and column = i mod C. This works for any size array and any valid index. It is the basis for converting between flat and 2D layouts in memory-mapped files, GPU kernels, and serialization formats.
How to Use This Calculator
Enter any three of the four quantities — row, column, number of columns, or flat index — and the calculator computes the fourth via the row-major formula.
1. Edit any field
Change row, column, number of columns, or flat index. The other three update automatically using index = r · C + c and its inverse r = ⌊i / C⌋, c = i mod C.
2. Use realistic presets
Presets cover common values: rows and columns from 0 to 10, num_cols from 2 to 64, and flat indices covering the first few elements up to 100.
3. Read the result and verdict
The result card shows the featured value plus a validity check — whether the current (r, c) fits within the C-wide rows and whether the flat index is in range.
4. Inspect the layout map
The 2D grid diagram shows the flat index of every cell, with the current element highlighted. You can see exactly how row-major order assigns increasing indices left-to-right, top-to-bottom.
5. Check the charts
The first chart shows flat index vs (row, column) position. Advanced mode adds a full flat-index grid — a heat-map style view of how indices are laid out in memory.
6. Switch to Advanced for depth
Advanced mode adds the flat-index grid chart, sensitivity checks, and companion metrics including the memory address of the current element, the byte offset, and the equivalent column-major index for comparison.
What This Tool Offers
Built around the row-major formula index = row · num_cols + column — the standard way C, C++, Java, and most modern languages store 2D arrays in flat memory.
Four-way sync
Edit row, column, num_cols, or flat index — the other three update instantly. Both directions work (forward and inverse formulas).
2D layout map
A visual grid showing the flat index of every cell, with the current element highlighted, and clear row boundaries.
Validity verdict
Each result is checked for out-of-range coordinates (column beyond C−1) and negative or excessive indices, with a clear badge.
Multi-curve charts
Flat index vs position, plus a heat-map grid chart showing how indices are laid out across all cells.
Byte-level metrics
Memory address and byte offset of the current element, plus the column-major equivalent index for direct comparison.
Reference tables
Full flat-index lookup for a sample array, row-major vs column-major comparison, and a variable reference.
Reference Tables & Conversions
A 4-way converter, a lookup table of flat indices for a sample array, and a row-major vs column-major comparison.
4-way converter
Flat Index Lookup — 4 × 4 Array
Row-major flat indices for every cell in a 4-column, 4-row array. The same layout shown in the diagram above, as a table.
| (r, c) | Flat index i | Byte offset (4 B int) | Column-major i |
|---|
Row-Major vs Column-Major
Same 3×4 array, two different memory layouts. The flat indices are very different.
| Element (r, c) | Row-major index | Column-major index | Difference |
|---|---|---|---|
| (0, 0) | 0 | 0 | 0 |
| (0, 1) | 1 | 3 | −2 |
| (0, 2) | 2 | 6 | −4 |
| (1, 0) | 4 | 1 | +3 |
| (1, 1) | 5 | 4 | +1 |
| (1, 2) | 6 | 7 | −1 |
| (2, 0) | 8 | 2 | +6 |
| (2, 2) | 10 | 8 | +2 |
Variable Reference
| Symbol | Meaning | Typical range | Formula (row-major) |
|---|---|---|---|
| r | Row index (0-based) | 0 – 10⁹ | ⌊i / C⌋ |
| c | Column index (0-based) | 0 – 10⁹ | i mod C |
| C | Number of columns | 1 – 10⁹ | stride / element size |
| R | Number of rows | 1 – 10⁹ | total / C |
| i | Flat index (row-major) | 0 – 10¹⁵ | r · C + c |
| icol-major | Flat index (column-major) | 0 – 10¹⁵ | c · R + r |
| bytes | Byte offset in memory | 0 – 10¹⁶ | i · sizeof(element) |
What Does index = row · num_cols + column Measure?
The formula gives the position of an element in a flat, 1-dimensional array that represents a 2D grid. It is the bridge between the mental model of a 2D table (rows and columns) and the physical layout of memory (a single contiguous block of bytes). Every language and library that supports 2D arrays uses one of the two layout conventions — row-major or column-major — and the formula encodes exactly which one.
The Row-Major Index Formula
In row-major order the array is stored as consecutive rows: row 0 completely, then row 1, then row 2, and so on. To find the flat index of element (r, c):
The r · num_cols term counts how many complete rows precede the target row, and c counts how many elements come before the target inside its own row. The inverse formulas recover (r, c) from the flat index:
column = index mod num_cols
For column-major order (Fortran, MATLAB, Julia), the roles are swapped:
Row-Major Variables
| Symbol | Meaning | Notes |
|---|---|---|
| r | Row index | 0-based; 0 is the first row |
| c | Column index | 0-based; 0 is the first column |
| C | Number of columns | The stride between consecutive rows |
| R | Number of rows | Used only for column-major formulas |
| i | Flat index | 0 to R·C − 1 for a full array |
Why the Layout Matters
Row-major and column-major give the same set of elements but completely different flat indices. The same (r, c) = (1, 2) is index 6 in a 4-column row-major array but index 9 in a 3-row column-major array. Every serialization format, memory-mapped file, GPU memory access pattern, and interop boundary between languages has to specify which convention it uses.
The layout also determines cache performance. In row-major order, iterating along a row touches consecutive addresses — the CPU prefetcher streams the data in quickly. Iterating along a column jumps by C elements (or C · sizeof(element) bytes) per step, missing the cache on every access. This is why the loop order matters so much for numerical code: the same computation on the same array can run 10× faster if the inner loop iterates along the memory-contiguous axis.
Language interoperability is another source of pain. C, C++, Java, C#, Python (NumPy default), and Go are row-major. Fortran, MATLAB, Julia, and R are column-major. When you pass a 2D array between them — say, from Python to a Fortran LAPACK routine — you often have to explicitly transpose the array, or reverse the arguments to the formula, otherwise the two sides will interpret the flat buffer differently and produce silently wrong results. This is one of the classic bug sources in scientific computing.
Finally, the formula generalizes to higher dimensions trivially: for a 3D array with dimensions (D0, D1, D2), the flat index is i = x0 · D1 · D2 + x1 · D2 + x2. Each successive dimension's stride is the product of all following dimensions' sizes. Row-major indexing is really the application of a sequence of multiplications by decreasing strides — an idea that appears in every array library, GPU memory kernel, and tensor framework.
Worked Examples
i = r · C + c = 2 · 4 + 3 = 11
r = ⌊11 / 4⌋ = 2
c = 11 mod 4 = 3
So (r, c) = (2, 3)
i = 5 · 10 + 7 = 57
i = 0 · C + 0 = 0
Byte offset = 0 · 8 = 0 bytes
indexcol-major = c · R + r = 2 · 3 + 1 = 7
Frequently Asked Questions
Because in row-major order you stride over an entire row's worth of elements to get from one row to the next. A row contains num_cols elements, so moving down one row shifts the flat index by num_cols. If you used num_rows, you would be describing column-major order instead — where moving down a column shifts the index by the number of rows. The two are mirror images, and the formula tells you which layout you are working in.
Row-major is used by C, C++, Java, C#, Python (including NumPy by default), Rust, Go, Swift, Kotlin, JavaScript (for typed arrays), and most modern general-purpose languages. Column-major is used by Fortran, MATLAB, Julia, R, and the BLAS/LAPACK linear algebra libraries. Some languages — notably NumPy — let you choose the order when creating an array, with the flag order='C' or order='F'. The default in NumPy is row-major, but many scientific Python workflows explicitly use column-major to interface with Fortran libraries.
Yes — the formula generalizes. For a 3D array with dimensions (D0, D1, D2) in row-major order: index = x0 · D1 · D2 + x1 · D2 + x2, where (x0, x1, x2) is the coordinate. Each dimension's stride is the product of the sizes of all following dimensions. For 4D and beyond the pattern continues. The general principle is that dimension k's stride is the product of dimensions k+1 through the last. This is exactly how NumPy, PyTorch, TensorFlow, and every tensor framework compute flat offsets, and it is why they expose the "stride" of each dimension as a first-class concept.
No — the formula assumes all rows have the same number of columns (a rectangular 2D array), which is the standard case in C-style arrays and NumPy's default. For "jagged" or "ragged" arrays (each row has a different length), you cannot compute a flat index from (r, c) alone; you need the row offsets explicitly. Jagged arrays are typically represented as arrays of arrays, each with its own length, rather than as a single flat buffer with a stride. This is why they are slower to traverse than flat 2D arrays.
The byte offset is the flat index multiplied by the size of each element in bytes. For an int32 array, the element size is 4 bytes; for a double it is 8. The byte offset tells you exactly where in the raw memory buffer the element lives. This matters when you are working with memory-mapped files (mmap), GPU kernels, DMA transfers, or FFI boundaries — anywhere you interact with raw memory rather than a language's native array abstraction. The formula is: byte_offset = i · sizeof(element). Our calculator shows this in the companion metrics.
Yes — the inverse formula is exact and uses only integer arithmetic: row = ⌊index / C⌋ and column = index mod C, where C is the number of columns. Integer division and modulo are exact for any non-negative index and any positive C, so no precision is lost. Our calculator uses this in the "index → row, column" direction. The only subtlety is that if index is out of range (≥ R · C), the formula still returns numbers, but they describe a row that does not exist in the array — the calculator flags this with the validity badge.
It depends entirely on the layout. For a row-major array, iterating along rows (outer loop over rows, inner loop over columns) is fast because consecutive inner iterations touch consecutive memory addresses — the CPU cache line is fully utilized, and the hardware prefetcher can stream the data. Iterating along columns on the same array does a cache miss on nearly every access. The speed difference can easily be 5–10×. The rule of thumb: on a row-major array, keep the last varying index as the innermost loop; on a column-major array, do the opposite. This single change is one of the highest-leverage optimizations in numerical code.
That variant appears when the array is 1-indexed rather than 0-indexed. In 1-based indexing (used by Fortran, MATLAB, and most mathematical notation), the first row is row 1, the first column is column 1, and the first element is index 1. Converting to 0-based gives index0 = (row − 1) · num_cols + (col − 1) = row · num_cols + col − num_cols − 1, which is messier. This calculator uses 0-based indexing throughout, matching C, Java, Python, and every modern general-purpose language. If you are translating a formula from a textbook or a Fortran source, double-check the base before using it.
Variables
| Symbol | Quantity | Unit |
|---|---|---|
| index | Flat memory index | |
| row | Row index (0-based) | |
| num_columns | Total number of columns | |
| column | Column index (0-based) |
What it means
In row‑major order, the elements of a multi‑dimensional array are stored in contiguous memory row by row. For a 2D array with dimensions rows × columns, the 1D index of element (i, j) (0‑based) is computed as i * num_columns + j. This layout is used in languages like C, C++, and Python (with lists of lists often not contiguous, but conceptually row‑major is common). Conversely, column‑major order (used in Fortran and MATLAB) computes index as j * num_rows + i. Row‑major allows efficient sequential access along rows, which improves cache locality for many algorithms. The formula is fundamental for accessing array elements in low‑level programming, optimizing loops, and understanding memory usage. It also applies to higher dimensions: for 3D, index = ((i * depth) + j) * width + k. Knowing the memory layout is crucial for performance, especially in scientific computing, graphics, and machine learning where large multi‑dimensional data is processed. The concept is also used in image processing (e.g., pixel data) and in designing data structures that mimic arrays.
Worked example
2D Array Index – Two Examples
Real‑World| Parameter | Value |
|---|---|
| row | 300 |
| col | 500 |
| num_columns | 800 |
| Parameter | Value |
|---|---|
| row | 42 |
| col | 127 |
| num_columns | 256 |
Common mistakes
- Column count: The number of columns must be known and constant for all rows.
- Zero‑based indices: The formula assumes row and column are zero‑based (starting at 0). If using 1‑based, adjust accordingly.
- Row‑major vs. column‑major: Row‑major is common in C, but column‑major is used in Fortran; verify the memory layout.
- Bounds checking: Ensure row < num_rows and column < num_columns to avoid out‑of‑bounds access.
- Stride: If the array has padding or non‑contiguous storage, the simple formula may not hold.
Applications
Row‑major order indexing for a 2D array maps a (row, column) pair to a single index using the formula `index = row * num_columns + column`. This is the standard memory layout for multi‑dimensional arrays in C and C++, as well as for many other languages when using contiguous storage. Understanding this mapping is essential for efficient access, loop optimisation, and when interfacing with low‑level memory (e.g., image processing, matrix multiplication). Engineers use this formula to flatten multi‑dimensional data for storage, to optimise cache locality, and to implement algorithms that operate on matrices and images. It is also critical for understanding how compilers and hardware handle arrays, directly impacting performance.
- Memory layout of multi‑dimensional arrays
- Optimisation of nested loops for cache performance
- Image processing and pixel access
- Linear algebra and matrix operations
- Data serialisation and storage
Related calculators · Data Structures
Recently updated formulas
Suggest an improvement
Found a mistake? Have a better example? Let us know.
You may send up to 3 suggestions per 24 hours.