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?
CodePudding user response:
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.
CodePudding user response:
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.
CodePudding user response:
Problem solved based on this comment from @abelenky: long total = 0
.
CodePudding user response:
//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);
}
}