Home > Back-end >  How to sum the elements of a 2D array in C recursively
How to sum the elements of a 2D array in C recursively

Time:04-08

I tried this in many ways, it would've been much easier if I could use iteration instead of recursion, but this is the assignment.

So far, I've come with the idea to separate the sum. One function to make the sum of a colum recursively, and to call that function so I can add all the sums into another function to get the total. Can anyone help me with my code or if you have a better/simpler idea, please share.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

float sum_colum(float b[], int m){

    float result;

    if (m == 0)
        result = 0;
    else
        result = sum_colum(b, m-1)   b[m-1];

    return result;
}

float sum_total(float a[][100], int n, int m){

    float f = 0;
    int i = 1;

    float col = sum_colum(b, );
    while(i <= n){
        f  = col[i];
        n--;
    }
    return f;
}
void main(){

    float x[100][100];
    int i, j, n, m;

    printf("Number of rows: "); scanf("%d", &n);
    printf("Number of colums: "); scanf("%d", &m);

    for(i=0; i<n; i  ){
        for(j=0; j<m; j  ){
            printf("x[%d][%d] = ", i, j);
            scanf("%f", &x[i][j]);
        }
    }

    printf("The sum of elemets of a 2D array is: %.2f", sum_total(x, n, m));
}

CodePudding user response:

  1. Solve recurse solution for an 1D Array. Recursion begins at the end (last index of row), stops when it hits the first element at 0 index. In a 2D matrix every row is an 1D Array.
float sum_row (float row[], int ci) {
    return (0 == ci) ? row[ci] : row[ci]   sum_row (row, ci - 1) ;
}
  1. Now extend that logic to every row in the matrix. Again we recurse from last row and stop when we arrive at row-index 0.
float sum_matrix (float mat[][MAX_COLS], int ri, int cols) {
    if (0 == ri)
        return sum_row (mat[0], cols);
    else
        return sum_row (mat[ri], cols)   sum_matrix (mat, ri -1, cols);
}

Now to test it, since C array-indexes begin at 0 we pass MAX_ROWS-1 & MAX_COLS-1 as highest values row-index & column-index can take respectively.

When you read rows & columns values from the user, then you'll use:

float sum = sum_matrix (mat, rows - 1, columns - 1);
#include <stdio.h>

#define MAX_ROWS    10
#define MAX_COLS    10

int main() {
    float mat[MAX_ROWS][MAX_COLS];

    for (int ri = 0; ri < MAX_ROWS;   ri) {
        for (int ci = 0; ci < MAX_COLS;   ci) {
            mat[ri][ci] = (float) ri * ci;
            printf (".6f ", mat[ri][ci]);
        }
        putchar('\n');
    }
    float sum = sum_matrix(mat, MAX_ROWS-1, MAX_COLS-1);
    printf ("2D Matrix Sum with Recursion: %f\n", sum);
}

Note:

  • Recursion is not advised when an iterative solution is cheaper on resources (time space).
  • If matrix float values are too large( /-), sum may overflow/underflow. You may want to use double storage for sum; and both function shall return a double value. As of today in mainstream systems, double(using 8 bytes) can store larger range of values as opposed to float(4 bytes).

CodePudding user response:

Recursion is pretty much always the wrong solution to any problem: it is slow, dangerous, memory consuming and often needlessly hard to read or implement.

That being said, there's a rather simple way to do this and that's to "mangle" the 2D array into a 1D one. All items are guaranteed to be allocated adjacently. (There's some language lawyer aspects of addressing an inner array out of bounds, but I'll ignore them since recursion is bad practice to begin with.)

float sum (size_t size, float arr[size])
{
    return size==0 ? 0.0f : 
                     arr[size-1]   sum(size-1, arr);
}

You'd call it like this:

int main (void)
{
    float x[3][3] = 
    {
        {1.0f, 2.0f, 3.0f},
        {4.0f, 5.0f, 6.0f},
        {7.0f, 8.0f, 9.0f},
    };

    printf("sum: %f\n", sum(9, (float*)x));
}

The resulting machine code is some horrible parallization goo where some compilers fail to tail-call optimize/inline even with main() in the same translation unit. This with my version which is much more efficient than one breaking down the array in rows and columns. One of the main problems here is that the recursion can't predict when it will end since it apparently can't tell the size at compile-time (gcc seems to do a better job than clang here, but the machine code is very difficult to read).

Now compare that utter crap with a plain loop:

float sum=0;
float* ptr = (float*)x;
for(size_t i=0; i<9; i  )
  sum =ptr[i];

Resulting in this nicely optimized asm:

.LCPI0_0:
        .quad   0x4046800000000000              # double 45
main:                                   # @main
        push    rax
        movsd   xmm0, qword ptr [rip   .LCPI0_0] # xmm0 = mem[0],zero
        mov     edi, offset .L.str
        mov     al, 1
        call    printf
        xor     eax, eax
        pop     rcx
        ret
.L.str:
        .asciz  "sum: %f\n"

From this we can conclude that using recursion wasn't just a bad idea, it was complete madness. I would ask your teacher why they are teaching you how to write bad programs instead of focusing on how to write good programs.

  • Related