Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Calculate the statistical mode of an array 3

Status
Not open for further replies.

BobXb

MIS
Mar 6, 2005
4
US
I'm working on a call monitoring app at the office and along with the other data that is to be processed, my manager wants the app to calculate and print onscreen the statistical mode for the number of phone calls made by each department. The mode is the most common number, so if a dept. has 5 employees, the manager might enter in the following numbers for daily phone totals: 20, 20, 30, 35, 40.(in that set, the mode would be 20, since it is the most frequent number)

The code I develop has to account for more than one mode, for example: 20, 20, 30, 30, 40 (20 and 30 are both modes).

This is the code segment I have so far, it compiles but returns garbage. I'm using dynamic arrays to store the data, since the number of employees varies from dept. to dept. Any assistance would be appreciated!

Code starts here:
============================================
Code:
//calculates and displays the mode
void calcMode(float array[], int elems)
{
	// declare variables
	int x, y, i;	//loop counters
	int sum = 0;	//stores the count for each value
	int *freq;		//dynamic array to store the sums
	int hiFreq = 0;	//stores the highest number of occurrences
	freq = new int [elems];
	
	// determine the frequency of each value in array
	for ( x = 0; x < elems; x++ )
	{
		for ( y = 0; y < elems; y++ )
		{
		if ( array[x] == array[y] )
			{
			sum++;
			freq[x] = sum;
			}
		}
	}

	cout << "Frequency is: " << freq[x] << endl; //MISTAKE: the frequency is not correct

	if (hiFreq < freq[x] )
		hiFreq = freq[x];
	
	// display the mode
	cout << "\nThe mode was counted: " << hiFreq << " times." <<endl //MISTAKE: always returns 0
		<< "The mode(s) are: " << endl;

		//MISTAKE: no numbers are displayed when the following code is run
		for ( i = 0; i < elems; i++ ){
		if ( hiFreq == freq[i] )
			cout << array[i] << endl;
		}
}
 
PS -
Since I'm having so many problems with the code I posted above, if it's easier for me to scrap that and start over, no problem. I just want something that works!

Also, if it's REALLY necesary for me to post all of the code for the app I can, but the rest of it is working fine - I just need code to count the frequency of each value in an array, determine which value(s) appear most frequently, and then display those two pieces of info:
1. which value(s) are most common
2. how often they occur

Thanks!!
 
> freq = new int [elems];
I'm not sure if this initialises all the elements of the array you allocated to 0 or not. If it doesn't, then your stats are immediately off because of all the junk in this memory

Code:
for ( int i = 0 ; i < elems ; i++ ) { freq[i] = 0; }

> cout << "Frequency is: " << freq[x] << endl;
This code is outside the for ( x = 0; loop, so the value you end up indexing is for the case when x == elems (which is outside the array).

My guess is the code should be this
Code:
    // determine the frequency of each value in array
    for ( x = 0; x < elems; x++ )
    {
        for ( y = 0; y < elems; y++ )
        {
        if ( array[x] == array[y] )
            {
            sum++;
            freq[x] = sum;
            }
        }

        // Moved inside the loop
        cout << "Frequency is: " << freq[x] << endl;

        if (hiFreq < freq[x] )
            hiFreq = freq[x];
    }

--
 
Salem,

Thanks! Both of your suggestions helped:
1) Initializing the array took care of the primary garbage output issue, so that the numbers are now making more sense
2) Moving that cout statement has the frequency printing at exactly the right point.

I've got two issues left to work out:
1) The counts for frequency are off - the frequency for employee #1 is always reported as 1, and all others are 0
2) I'd like the app to output the mode only once - if 20 is the mode because 3 employees made 20 calls, I'd like to have 20 listed once, not 3 times.

I haven't polished this at all, still working on basic functionality, but here's all of the code for the mode, in case it will help for you to be able to complie it yourself.

Thanks!!
Bob

Code:
// This program gathers statistical data about the number of phone calls
// employees make per day and calculates the mode.

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#using <mscorlib.dll>
using namespace std;
using namespace System;

// Function prototypes
void sortArray(float [], int);
void showArray(float [], int);
void calcMode(float [], int);


int main()
{
	float *calls, total = 0, average;
	int numEmployees, count;
	char ans;

	do{
	
	cout << "\nWelcome to the Call Statistics calculating program!\n";
	
	do	{
		cout << "How many employees made calls today? ";
		cin >> numEmployees;
	
		if (numEmployees < 1)
			{
			cout << "The number of employees must be greater than or equal to 1."
				 << endl << endl;
			}

	} while (numEmployees < 1);

	calls = new float[numEmployees];  // Allocate memory
	
	// Get the calls figures from the user
	cout << "\nPlease enter the calls data below.\n";
	for (count = 0; count < numEmployees; count++)
	{
		do{
		cout << "Employee " << (count + 1) << ": ";
		cin >> calls[count];

		if (calls[count] < 0)
			cout << "The number of calls must be greater than or equal to 0."
			<< endl << endl;

		} while (calls[count] < 0);
	}

	//Sort the array
	cout << "\nThe unsorted values are:\n";
	showArray(calls, numEmployees);
	sortArray(calls, numEmployees);
	cout << "The sorted values are:\n";
	showArray(calls, numEmployees);

	//call the calcMode functions
	calcMode(calls, numEmployees);

	cout << "\nWould you like to run this program again? (y)es or (n)o: ";
    cin >> ans;
    }  while ( (ans == 'y' || ans == 'Y') );

	// Free dynamically allocated memory
	delete [] calls;

	//system("pause");
	return 0;
}


// This function is a bubble sort in ascending order
// (low to high).  elems is the number of elements in the array.  
void sortArray(float array[], int elems)
{
	bool swap; 
	float temp;

	do
	{
		swap = false;
		for (int count = 0; count < (elems - 1); count++)
		{
			if (array[count] > array[count + 1])
			{
				temp = array[count];
				array[count] = array[count + 1];
				array[count + 1] = temp;
				swap = true;
			}
		}
   } while (swap);
}

// This function displays the contents of array. elems is the
// number of elements in the array.
void showArray(float array[], int elems)
{
	for (int count = 0; count < elems; count++)
		cout << array[count] << " ";
	cout << endl << endl;
}

// This function calculates and disp[lays the statistical mode.
void calcMode(float array[], int elems)
{
	// declare variables
	int x, y, i, sum, *freq, hiFreq = 0;
	freq = new int [elems];
	for ( x = 0; x < elems; x++ )
		freq[x] = 0;
	
	// determine the frequency of each value in array
	for ( x = 0; x < elems; x++ )
	{
		for ( y = 0; y < elems && array[x] == array[y]; y++ )
		{
		//if ( array[x] == array[y] )
			sum++;
			freq[x] = sum;
			}
		cout << "Frequency is: " << freq[x] << endl;
		}

	if (hiFreq < freq[x] )
		hiFreq = freq[x];
	
	// display the mode
	cout << "\nThe mode is: " << hiFreq << endl
		<< "for the following number(s) of calls: " << endl;

		for ( i = 0; i < elems; i++ ){
		if ( hiFreq == freq[i] )
			cout << array[i] << endl;
		}
}
 
Some remarks about your includes in VC++:
Code:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <stdlib.h>
Move last 3 includes in stdafx.h (TODO section):
Code:
#include <iostream>
#include <iomanip>
#include <cstdlib>
// avoid old form like stdlib.h in C++...
Then recompile stdafx.cpp and use precompiled headers again (fast compilation)...
 
if you dont need to see the frequency for each value in the array

you might use something like
Code:
#include  <math.h>
#define FP_ERROR_LIMIT = 0.00001

void calcMode2(float array[], int elems)
{
    float mode  = 0;
    int   count = 0;
    for (int i = 0; i < elems;i++)
    {
	if (array[i] > mode && abs(array[i]-mode)>FP_ERROR_LIMIT)
        {
            mode = array[i];
            count = 1;
        }
        else if  (abs(array[i]-mode)<=FP_ERROR_LIMIT)
        {
	    count++;
        }
    }
    cout << "\nThe mode is: " << mode << "\nfor the following number(s) of calls: " << count << endl;
}


"If it could have gone wrong earlier and it didn't, it ultimately would have been beneficial for it to have." : Murphy's Ultimate Corollary
 
ignore that - it doesnt calculate the mode - sorry

"If it could have gone wrong earlier and it didn't, it ultimately would have been beneficial for it to have." : Murphy's Ultimate Corollary
 
This should be better - the frequency array might be redundant now unless you are going to use it for something else
Code:
#include  <math.h>
#define FP_ERROR_LIMIT = 0.00001

void calcMode(float array[], int elems)
{
    // declare variables
    int sum    = 0;               //temporary store for the frequency of each element
    int hiFreq = 0;               //store for the highest frequency found
    int *freq  = new int [elems]; //store for all the frequencies found

    //initialise frequency array
    for ( int i = 0; i < elems; i++ )
    {
        freq[x] = 0;
    }

    // determine the frequency of each value in array
    for (int x = 0; x < elems; x++)
    {
        float temp = array[x];
        sum = 0;

        //iterate through the array looking for equal values
        for (int y = 0; y < elems; y++)
        {
            if (abs(array[y]-mode) <= FP_ERROR_LIMIT)
            {
                sum++;
            }
        }
        cout << "Frequency for "<< temp <<" at index "<< x <<" is: " << sum << endl;

        //store frequency
        freq[x] = sum;

        //check highest frequency
        if ( hiFreq < sum )
        {
            hiFreq = sum;
            mode = temp;
        }
    }

    // display the mode
    cout << "\nThe mode is: " << hiFreq << endl << "for the following number(s) of calls: " << mode << endl;

    delete [] freq;
}

"If it could have gone wrong earlier and it didn't, it ultimately would have been beneficial for it to have." : Murphy's Ultimate Corollary
 
Thanks for all of the help and suggestions! Based on some research, reviewing loop basics, and working with the code, I came up with the following function to calculate the mode. It's still rough - I need to format the output, hide some of the info I've been displaying for debugging purposes, and add validation to manage non-numeric characters, but this has all of the basic functionality I need. I'll review your suggestions to look for more elegant and efficient ways to calculate the mode. Really appreciate all of the assistance - I'm definitely going to review some of the other posts, and sure I'll be posting again from time to time.

Thanks again-
Bob


Code:
// This function calculates and displays the statistical mode.
void calcMode(float array[], int elems)
{
        // declare variables
        int x, y, i, sum, *freq, hiFreq = 0;
        freq = new int [elems];

        for ( x = 0; x < elems; x++ )
                freq[x] = 0;
       
        // determine the frequency of each value in array
        for ( x = 0; x < elems; x++ )
        {
                sum = 0;  // re-initalize sum each time
                for ( y = 0; y < elems; y++ )
                {
                    if ( array[x] == array[y] ) // runs every time now
                            sum++;
                }
                freq[x] = sum;
                cout << "Frequency is: " << freq[x] << endl;

                if (hiFreq < freq[x] )  // now inside the outer loop
                    hiFreq = freq[x];
        }
       
        // display the mode
        cout << "\nThe mode occurred the following number of times: " << hiFreq << endl
			<< "The mode is: " << endl;

        int lastPrintedValue = -1;
        for ( i = 0; i < elems; i++ )
        {
                if ( hiFreq == freq[i] && array[i] != lastPrintedValue )
                {
						cout << fixed << showpoint << setprecision(0);
                        cout << array[i] << endl;
                        lastPrintedValue = array[i];
                }
        }
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top