Average, Median and Mode

How can i get this to calculate the average, median and mode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  #include <iostream>
#include <iomanip>
#include <string>
#include <time.h>

using namespace std;

int main()
{
	int* Num_students;// to dynamically allocate an array
	int Num_students_surveyed;//number of student surveyed
	int count;//counter variable in the loop
	int total;//to calculate the total of movies watched
	double mode;
	double average;//to calculate the average
	double median;//Calculate the median of movies watched

//Ask about the number of students surveyed
	cout << "How many student are surveyed?" << endl;
	cin >> Num_students_surveyed;

	//Dynamically allocate an array large enough to hold the number of student surveyed
	Num_students = new int[Num_students_surveyed];
	cout << endl;
	cout << "______________________________________________________________________" << endl;

	//Get the number of movies watched by each student
	cout << "How many movies did each of the students watch ? " << endl;
	for (count = 0; count < Num_students_surveyed; count++)
	{
		cout << "Student#" << count + 1 << ": ";
		cin >> Num_students[count];
	}
	//Calculate the totale of movies watched
	total = Num_students[count];
	//Calculate the average of movies watched
	average = total / Num_students_surveyed;
	//Show the total and averaged of movies watched
	{
		cout << "The mode of movies watched is:" << total << " movies." << endl;
	}

	{
		cout << "The Average of movies watched is:" << average << "movie." << endl;
	}

	//Calcullate and show the median of movies watched
	median = total / 2;

	{
		cout << "The median of movies watched is:" << median << "movies." << endl;
	}

	//Free dynamically allocated memory
	delete[] Num_students;
	Num_students = 0; //Make the rest of unused arrays NULL

	return 0;
}
start here:
total = Num_students[count]; what does this do? I don't think this does what you think it does.
//it goes out of bounds, potentially, as count was incremented one last time to exit the loop.
//and its not the total, its one item, if it were a valid location

consider: total up the values as they are input by user? change the above to += and put it inside the loop.

average = total / Num_students_surveyed; //this only works if total is correct. also, do you understand integer division vs floating point result? you need to cast one of those as a double if you want the double result. If you want the int result, average's type is wrong.

Last edited on
Also since this is C++ you should be defining your variables close to first use, not in one big glob at the beginning of some scope.

If possible prefer std::vector over arrays, especially dynamically allocated arrays.

can you show me an example of how i would total up the values and put it in a loop ?
can someone tell me if my mode calculation output is right ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <time.h>
using namespace std;

// Function prototypes
double retrieveMean(int*, int);
double calculateMedian(int*, int);
int calculateMode(int*, int);

int main()
{
	cout << "                                   *Movie Statistics Program*\n\n";
	cout << "_______________________________________________________________/" << endl;
	int* nums;			// dynamically allocated array
	int num_students;	// To hold the number of students
	char repeat = ' ';

	//Do while loop to get number of students and also to warn a user if they enter a number less than 0
	do
	{

		// user enters how many students were surveyed
		cout << "How many students were surveyed? : ";
		cin >> num_students;

		while (num_students < 0)
		{
			cout << "Invalid number of students!\n";
			cout << "Enter in how many students were surveyed: ";
			cin >> num_students;
		}

		// Dynamically array to hold number of students asked
		nums = new int[num_students];

		// for loop to get the number of movies seen by each student asked in the survey.
		for (int count = 0; count < num_students; count++)
		{
			cout << "Number of movies seen by student #" << (count + 1) << ": ";
			cin >> nums[count];

			// Determine input validation.
			while (nums[count] < 0)
			{
				cout << "Enter a number higher than zero: ";
				cout << "\nNumber of movies seen by student #" << (count + 1) << ": ";
				cin >> nums[count];
			}

		}
		// Just adds spacing and title of report for the output of median, mean, and mode
		cout << endl;
		cout << endl;
		cout << endl;
		cout << "                               *Movie Statistcs Report of Mean, Median, and mode*   " << endl;
		cout << "____________________________________________________________________________________" << endl;
		// set decimals points to 2 places
		cout << fixed << showpoint << setprecision(2);

		// outputs the mean
		cout << "The mean is: ";
		cout << retrieveMean(nums, num_students) << endl;

		// outputs the median
		cout << "The median is: ";
		cout << calculateMedian(nums, num_students) << endl;

		// outputs the mode
		cout << "The mode is: ";
		cout << calculateMode(nums, num_students) << endl;

		// frees up memory
		delete[] nums;
		nums = 0;		

		// while loop to start over or end survey
		cout << "Do you want to start this survey over? ";
		cin >> repeat;


	} while (repeat == 'Y' || repeat == 'y');
	cout << "                                      Have a great day then ! \n";

	return 0;
}

gets//mean

double retrieveMean(int* nums, int num_students)
{
	double total = 0;
	double average_num;

	for (int count = 0; count < num_students; count++)
	{
		total += nums[count];
	}
	average_num = total / num_students;
	return average_num;
}

//gets median

double calculateMedian(int* nums, int num_students)
{
	double median = 0.0;
	cout << fixed << showpoint << setprecision(2);

	if (num_students % 2 == 0)
	{
		median = (nums[num_students / 2] + nums[(num_students / 2) + 1]) / 2.0;
		
	}
	else
		median = nums[num_students / 2];

	return median;
}

//gets mode

int calculateMode(int* nums, int num_students)
{
	int mode = 0;
	int val = 0;
	int index;


	for (index = 0; index < num_students; index++)
	{
		if (*(nums + index) == *(nums + (index + 1)))
		{
			mode++;
			val = *(nums + index);
		}
	}
	if (val > 0)
		return val;
	else
		return -1;

}
You are using pointer syntax unnecessarily, you can just use array syntax like you do in calculateMedian/""Mean. e.g. instead of *(nums + index), just do: nums[index].

Anyway, this is what [unit] tests are good for.

For example, given your code, you can write:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <string>

// BAD
int calculateMode(int* nums, int num_students)
{
	int mode = 0;
	int val = 0;
	int index;


	for (index = 0; index < num_students; index++)
	{
		if (*(nums + index) == *(nums + (index + 1)))
		{
			mode++;
			val = *(nums + index);
		}
	}
	if (val > 0)
		return val;
	else
		return -1;

}

bool Test_calculateMode()
{
    int nums[] = {3, 5, 5, 5, 3, 4, 4};
    return (calculateMode(nums, 7) == 5);
}

int main()
{
    if (Test_calculateMode())
    {
        std::cout << "Passed\n";   
    }
    else
    {
        std::cout << "Failed\n";   
    }
}


If you run this, you'll see the test fails. Why did it fail? Try going through the logic line by line to see. The crux of the issue is that you're (1) going out of bounds by doing nums[index + 1] (your post's line 133), but also (2) you are only keeping track of the last set of repeating numbers, not number of total occurrences of each number.

One option is, if you're allowed to manipulate the array while measuring it, would be to sort the array and then find the largest streak. (Copy the arrays elements into a temporary array if you're not allowed to re-order the elements)

This is the second time you've gone out of bounds (jonnin mentioned a previous instance of doing so). Be extra careful here. An easy check is saying "what is the largest value that index can be", and then seeing if the input into an array[some_index] is larger than that.
Last edited on
So what should I be doing ? I’m a beginner and you’re explaining advanced concepts that I don’t fully understand.
Can you break it down what I should be doing first to get an accurate mode
Most of my post was to show an example of a test that answers your previous question of "is my mode calculation right?".

Break it down like this:
1. You have an array of numbers, e.g. {5, 3, 5, 5, 3, 6, 4, 4, 6}
2. Sort the array so that the numbers are in ascending order: e.g. {3, 3, 4, 4, 5, 5, 5, 6, 6};
3. Find the longest "streak" of the same number in the data. This is now possible because the data is sorted. e.g. the longest streak here is 5. That is the mode.

There might be other ways to find the mode without sorting the data... but they would make things more complicated, imo. (edit: as dhayden showed, not necessarily more complicated, although sorting might be more efficient for large data sets)
Last edited on
Your calculateMedian() function assumes that the nums array is sorted from smallest to largest. You need to add code to sort it.

It also needs to be sorted for you to compute the mode.

Mode is deceptively complex. here is some pseudo-code that might help you out.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int
calculateMode(int *nums, int num_students)
{
    unsigned bestIdx=0;    // Index of a number with the highest frequency seen so far
    unsigned bestCount=1; // number of items in the highest frequency seen so far
    unsigned curCount = 1; // number of times the current value has been seen

    for (each item, starting with the second one, not the first) {
        if (the current item is the same as the one before it) {
            // There are multiple occurrences of this item
            increment curCount
        } else {
           // This item is different from the previous one.  If the previous item occurred
           // more times than the best one so far, then it becomes the new best one
           if (curCount > best Count) {
                bestCount = curCount;
                bestIdx = i - 1;  // the index of one of the items with the count.
          }
          curCount = 1;   // and indicate that this item has occurred once so far.
    }
    // When you get to the end of the loop, bestCount and bestIdx reflect the
    // most frequent item *unless* the most frequent item is the last one in the list
    // In that case we haven't checked it yet, so do it now
    if (curCount > bestCount) {
        bestCount = curCount;
        bestIdx = num_students-1;
    }
    // Now bestCount and bestIdx reflect the most frequent item.
    // You need to return the value. That's why we've been keeping track of bestIdx
    // all this time - it's the index of one of the items that appears most frequently
    return nums[bestIdx];
}

What information am I inserting specifically in the conditional statements ?
if (/*the current item is the same as the one before it*/)

This condition is within a loop. See http://www.cplusplus.com/doc/tutorial/control/ about loops.

The concepts of "current item" and "item that is before current item" should be understandable, if you understand loops.


[edit] Just in case you need a refresh about arrays; see http://www.cplusplus.com/doc/tutorial/arrays/
Last edited on
What information am I inserting specifically in the conditional statements ?
I urge you to try to understand the pseudocode and figure out what needs to be inserted. If something doesn't make sense, then ask about it.
Topic archived. No new replies allowed.