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.