简体   繁体   中英

Finding average of a given array

I am trying to answer the following:

Implement a function that is given an array of integers and the number of items. It should return the rounded (to the nearest integer) average of the numbers.

This is my code:

#include <stddef.h>
int CalculateAverage (const int array[], size_t size)
{
    
    int i;
    long total;
    float convert;
    int temp = 0;
    int average;
    if (size == 0)
    {
        return 0;
    }
    for (i=0; i<size; i++)
    {
        temp = total;
        total = temp + array[i];
    }
    
    convert = total;
    convert = convert / size;
    average = (convert > 0) ? convert + 0.5 : convert - 0.5;
    
    return average;
}

I can't use any functions. When I run the test on our class tutorial app I get (every time with different inputs):

Testing Report:
Running test: CalculateAverage(size=11)  --  Passed
Running test: CalculateAverage(size=13)  --  Failed

Done

I am not sure where is my mistake. I think it is related to negative/positive inputs. any suggestions?

Main issue: Uninitialized object

Below is bad as total is read, but not yet initialized nor assigned. @abelenky

long total;
 ...
    temp = total;

long not that wide

Good that OP is trying to accumulate the sum in a wider type, yet long is not certainly twice as wide as int *1 . Consider long long or intmax_t . Even those are not certain to be wider, yet commonly are wider.

Wrong rounding

convert + 0.5 not needed as prior convert / size already rounded. Floating point math not needed. Conversion to float risks losing precision. Use of double math with float object is curious.

Wrong type

Iterator i should match type of size .

Good use of const and size==0 detection


Proposed fix

#include <inttypes.h>
#include <stddef.h>

int CalculateAverage (const int array[], size_t size) {
  if (size == 0) {
    return 0;
  }
  intmax_t sum = 0;
  for (size_t i = 0; i<size; i++) {
    sum += array[i];
  }

  // Form a rounded average by subtracting/adding half the size before the division.
  // For handling ties and round to even obliges a little more code.
  sum = (sum < 0) ? sum - size/2 : sum + size/2;
  return (int) (sum / size);
}

*1 The width needed is the width of int plus the width of size_t . To truly handle very extreme averaging, takes additional code.

To add to the comments you could make it more understandable by accumulating the results of division and reminders of division in 2 varaibles like this:

int CalculateAverage(const int array[], size_t size) {
    if (size == 0) return 0;
    int sum_of_divided = 0, sum_of_remainders = 0;
    for (int i = 0; i < size; i++) {
        sum_of_divided += array[i] / size;
        sum_of_remainders += array[i] % size;
    }
    return sum_of_divided + sum_of_remainders / size;
}

This doesn't require floats and is thus not susceptible to floating point precision errors.

Problem solved based on this comment from @abelenky: long total = 0 .

 //Working example #include <stdio.h> #include <stddef.h> #include <math.h> void main() { float CalculateAverage (int array[], int arr_size) { int total=0; float average=0; if (arr_size == 0) { return 0; } for (int i=0; i<arr_size; i++) { total += array[i]; } printf("Size of array = %d", arr_size); printf("\nSum of array = %d", total); average = (float) total / arr_size; printf("\nActual average = %f", average); return average; } int numArray[] = {7, 8, 9, 11, 13}; int arr_size = sizeof(numArray)/sizeof(numArray[0]); //You can manually pass the array size if you don't want to use any built-in function float avg = CalculateAverage(numArray, arr_size); if(avg>0) { float tempNum = avg*10; float reminder = fmodf(tempNum, 10); if(reminder >= 5) { avg++; } printf("\nRounded off average = %d", (int)avg); } else{ printf("Average = %lf", avg); } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM