0

Good evening. I was trying to to have the following program give me the average and round the average. So far I have the following.

When using <math.h>'s round function it returns a zero. Yes I have tried compiling with -std=99, -lm and -fno-builtin. None of these seem to matter. It still returns zero.

It should be using the ave given by ComputeAverage. This is where I get strange output. The Average sometimes shows as 148.28 (which should be correct) when it is run.

However I noticed if I run it to close to the previous run I get the following examples: 2303125649788529278976.00, -31360458752.00, -319407486092479668309433442631680.00, and 2618000384.00.

Also please be aware I'm still adding to the code but have tried to make sure I remove anything that isn't useful to the current situation. The code is as follows.

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define _ISOC99_SOURCE

#define N 8

typedef struct _Matrix {
    double element[N][N];
} Matrix;


void PrintMatrix(Matrix a)
{
    int i;
    int j; 
    for (i=0; i<N; i++)
    {
        for (j=0; j<N; j++)
        {
            printf("%g ", a.element[i][j]);
        }//Inner for
        printf("\n");
    }//Outer For
}// printMatrix

float ComputeAverage(Matrix a)
{
    float sum;
    float average; 
    int i;
    int j; 
    for (i=0; i<N; i++)
    {
        for (j=0; j<N; j++)
        {   
            sum += a.element[i][j];
        }//inner for 
        average = sum / 64;
    }//for 
    //a.element[i][j];
    printf("Average = %.2f",average);
    printf("\n");
    // printf ("Testing Sum = %f", sum);
    //  printf("\n");
}// ComputeAverage

Matrix Q50 = {{16, 11, 10, 16, 24, 40, 51, 61,
    12, 12, 14, 19, 26, 58, 60, 55,
    14, 13, 16, 24, 40, 57, 69, 56,
    14, 17, 22, 29, 51, 87, 80, 62,
    18, 22, 37, 56, 68,109,103, 77,
    24, 35, 55, 64, 81,104,113, 92,
    49, 64, 78, 87,103,121,120,101,
    72, 92, 95, 98,112,100,103, 99}
};

int main(int argc, const char * argv[])
{
    Matrix M = {{154, 123, 123, 123, 123, 123, 123, 136,
        192, 180, 136, 154, 154, 154, 136, 110,
        254, 198, 154, 154, 180, 154, 123, 123,
        239, 180, 136, 180, 180, 166, 123, 123,
        180, 154, 136, 167, 166, 149, 136, 136,
        128, 136, 123, 136, 154, 180, 198, 154,
        123, 105, 110, 149, 136, 136, 180, 166,
        110, 136, 123, 123, 123, 136, 154, 136}};

    // need to implement PrintMatrix
    PrintMatrix(M);
    // need to implement ComputeAverage
    float ave = ComputeAverage(M);
    // need to implement round
    int dc = round(ave);
    //printf("Ave = %d\n",dc);

    return EXIT_SUCCESS;
}
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 1
    Your compiler isn't giving you warnings with that code? If not, turn them on (`-Wall -Wextra` for gcc and clang. You might need to compile with `-O` too to see the most important one). – Shawn Nov 10 '18 at 05:21
  • 1
    Why do you have `double element` and `float ComputeAverage`? There are 32-bits difference in the width. Further -- you `return` nothing from `ComputeAverage`, so you may as well make it `void`. – David C. Rankin Nov 10 '18 at 05:21
  • 1
    Also you should get a warning about uninitialized local variable `float sum;`, change it to `float sum = 0;`, and the function `ComputeAverage` should return `average`. – Barmak Shemirani Nov 10 '18 at 05:27

1 Answers1

2

You invoke Undefined Behavior by using the return of float ComputeAverage(Matrix a) (which returns no value) in float ave = ComputeAverage(M);

You invoke Undefined Behavior within the above Undefined Behavior by using sum uninitialized in sum += a.element[i][j];

You invoke Undefined Behavior within the both above Undefined Behavior by passing a float to round(ave) where round expects a double.

Solution -- Make ComputeAverage(Matrix a) type double and return average; (and clean up the warnings regarding Missing Braces in your Matrix initializers), e.g.

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define _ISOC99_SOURCE

#define N 8

typedef struct _Matrix {
    double element[N][N];
} Matrix;

void PrintMatrix (Matrix a)
{
    int i;
    int j; 

    for (i=0; i<N; i++) {
        for (j=0; j<N; j++)
            printf (" %3g", a.element[i][j]);
        putchar ('\n');
    }
}

double ComputeAverage(Matrix a)
{
    double sum = 0;
    double average; 
    int i;
    int j; 

    for (i = 0; i < N; i++) {
        for (j=0; j<N; j++)   
            sum += a.element[i][j];
         average = sum / 64.0;
    }

    return average;
}


Matrix Q50 = {{{ 16, 11, 10, 16, 24, 40, 51, 61 },
               { 12, 12, 14, 19, 26, 58, 60, 55 },
               { 14, 13, 16, 24, 40, 57, 69, 56 },
               { 14, 17, 22, 29, 51, 87, 80, 62 },
               { 18, 22, 37, 56, 68,109,103, 77 },
               { 24, 35, 55, 64, 81,104,113, 92 },
               { 49, 64, 78, 87,103,121,120,101 },
               { 72, 92, 95, 98,112,100,103, 99 }}};

int main (void)
{
    Matrix M = {{{ 154, 123, 123, 123, 123, 123, 123, 136 },
                 { 192, 180, 136, 154, 154, 154, 136, 110 },
                 { 254, 198, 154, 154, 180, 154, 123, 123 },
                 { 239, 180, 136, 180, 180, 166, 123, 123 },
                 { 180, 154, 136, 167, 166, 149, 136, 136 },
                 { 128, 136, 123, 136, 154, 180, 198, 154 },
                 { 123, 105, 110, 149, 136, 136, 180, 166 },
                 { 110, 136, 123, 123, 123, 136, 154, 136 }}};

    PrintMatrix (M);
    double ave = ComputeAverage(M);
    printf ("ave: %g\n", ave);
    int dc = round(ave);
    printf ("dc : %d\n", dc);

    return EXIT_SUCCESS;
}

Example Use/Output

$ ./bin/computeavg
 154 123 123 123 123 123 123 136
 192 180 136 154 154 154 136 110
 254 198 154 154 180 154 123 123
 239 180 136 180 180 166 123 123
 180 154 136 167 166 149 136 136
 128 136 123 136 154 180 198 154
 123 105 110 149 136 136 180 166
 110 136 123 123 123 136 154 136
ave: 148.281
dc : 148

Enable Compiler Warnings

Always compile with warnings enabled, and do not accept code until it compiles cleanly without warning. To enable warnings add -Wall -Wextra to your gcc or clang compile string. (add -pedantic for several additional warnings). For clang, instead you can use -Weverything (but that includes numerous extraneous warnings). For both gcc/clang, recommend:

 -Wall -Wextra -pedantic -Wshadow

For VS (cl.exe on windoze), add /W3 (or use /Wall but you will get quite a few extraneous non-code related warnings).

Read and understand each warning. They will identify any problems, and the exact line on which they occur. You can learn a lot by listening to what your compiler is telling you.

Let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Good morning, thank you for your response. I had originally had sum initialized to 0.0, and I had missed the return statement altogether :(. My question is do you have a link to the official documentation for the C libraries? The only documentation I found about the built in round function in C said it takes double/floats/longs so I wouldn't have considered changing the float values to doubles. Is there anything specific you suggest I read or listen to while studying to help with the learning? Or more practice than anything? – Tyreese Davis Nov 10 '18 at 18:17