15,847,263 members
See more:
In the following code I'm trying to calculate the mean and standard deviation of the number of molecules that are trapped in a square grid, but I'm not sure if I'm doing it well.

What I have tried:

/* CODE THAT CALCULATES THE MEAN, VARIANCE AND STANDARD DEVIATION IN A SQUARE SURFACE FILLED WITH CO AND O.*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

//define the dimensions of the grid
#define MAX_X 4
#define MAX_Y 4
//define the partial pressure of CO
#define XCO 0.300000

//define the states of a cell in grid`
typedef enum  { S_EMPTY, CO_OCCUPIED, O_OCCUPIED, S_NONE } gstate;

// help generate random coordinate of the grid
int gridrnd(int max)
{
return (rand() % max);
}

// generates random coordinates of the grid
int generate_coords(int* y, int* x )
{
if (!x || !y)
return 1;

*x = gridrnd(MAX_X);
*y = gridrnd(MAX_Y);

printf("(%d,%d)\n\n", *y, *x);
return 0;
}

void grid_init(gstate grid[MAX_Y][MAX_X])
{
for (int y = 0; y < MAX_Y; y++) {
for (int x = 0; x < MAX_X; x++) {
grid[y][x] = S_EMPTY;
}
}
}

double calculateMean(int array[], int size) {
double mean = 0;
for (int i = 0; i < size; i++){
mean += array[i];
mean /= size;
}
return mean;
}

int main()
{
int x = 0, y = 0;
gstate grid[MAX_Y][MAX_X];
int rx, ry, lx, ly, ux, uy, dx, dy;
int oxygen = 0, carbon_monoxide = 0, carbon_dioxide = 0;
int availcells = MAX_X * MAX_Y;
int rounds = 0;
int N =2* MAX_X * MAX_Y;
double num_co[N], num_o[N];

double average_co = 0.0, variance_co = 0.0, std_deviation_co = 0.0;
double average_o = 0.0, variance_o = 0.0, std_deviation_o = 0.0;
double sum_co = 0.0,  sum1 = 0.0;
double sum_o = 0.0,  sum2 = 0.0;

float r;

srand((unsigned)time(0));

// Initialize grid to be S_EMPTY
grid_init(grid);

while (rounds < N) // repeat till the grid is full
{
//LOCATE AN ENTRY OF THE MATRIX RANDOMLY
generate_coords(&y, &x);
rounds++;

//EVALUATE THE CHOOSEN SITE
switch (grid[y][x])
{
case S_EMPTY:
printf("IT'S S_EMPTY, LET'S FILL IT WITH A MOLECULE. FIRST LET'S GENERATE TO DECIDE IFIT WILL BE TRAPPED\n\n");

r = rand()/(float)RAND_MAX;

if(r < XCO || r == XCO){//CO is chosen
printf("r = %lf is less than XCO = %lf. We choose CO\n\n", r, XCO);
grid[y][x] = CO_OCCUPIED;
carbon_monoxide++;
availcells--;
for(int k=0;k<N;k++){
num_co[k] = carbon_monoxide;
}

}
else{//O is chosen
printf("r = %lf is greater than XCO = %lf. (O) is trapped\n\n", r, XCO);
grid[y][x] = O_OCCUPIED;
oxygen++;
availcells--;
for(int k=0;k<N;k++){

num_o[k] = oxygen;
}
}

break;

case CO_OCCUPIED:
printf("IT'S CO_OCCUPIED. PLEASE, GENERATE ANOTHER SITE ON THE SURFACE\n\n");
break;

case O_OCCUPIED:
printf("IT'S O_OCCUPIED. PLEASE, GENERATE ANOTHER SITE ON THE SURFACE\n\n");
break;

}

}

// Calculate mean (average) of each particle

for (int k = 0; k < N; k++) {
sum_co += num_co[k];
sum_o += num_o[k];
}
average_co = sum_co / (N);
average_o = sum_o / (N);

// Calculate standard deviation for each particle

for (int k = 0; k < N; k++) {
sum_co += (num_co[k] - average_co) * (num_co[k] - average_co);
sum_o += (num_o[k] - average_o) * (num_o[k] - average_o);
}
std_deviation_co = sqrt(sum_co / (N));
std_deviation_o = sqrt(sum_o / (N));

printf("The process took %d rounds\n\n", rounds);
printf("#co = %d\n\n", carbon_monoxide);
printf("#o = %d\n\n", oxygen);
//printf("#co2 = %d\n\n", carbon_dioxide);
printf("#availcells = %d\n\n",availcells);

printf("Mean_O = %.2lf\n", average_o);
printf("Mean_CO = %.2lf\n", average_co);
//printf("Mean_CO2 = %.2lf\n", average_co2);
printf("Standard deviation O = %.2lf\n", std_deviation_o);
printf("Standard deviation CO = %.2lf\n", std_deviation_co);
//printf("Standard deviation CO2 = %.2lf\n", std_deviation_co2);

return 0;
}

The code it's a it long, but the parts that are important for my questions are the following:

Here, I assign to an array the number of molecules of CO, O and CO2 calculated:
for (int k = 0; k < MAX_Y*MAX_X; k++) {
num_co[k] = (double)carbon_monoxide;
num_o[k] = (double)oxygen;
}

Here, I made the calculations for the mean and standard deviation of the number of molecules mentioned before
// Calculate mean (average)

for (int k = 0; k < N; k++) {
sum_o += num_o[k];
sum_co += num_co[k];
sum_co2 += num_co2[k];
}

average_o = sum_o / (N);
average_co = sum_co / (N);
average_co2 = sum_co2 / (N);

// Calculate standard deviation

for (int k = 0; k < N; k++) {
sum_o += (num_o[k] - average_o) * (num_o[k] - average_o);
sum_co += (num_co[k] - average_co) * (num_co[k] - average_co);
sum_co2 += (num_co2[k] - average_co2) * (num_co2[k] - average_co2);
}

std_deviation_o = sqrt(sum_o / (N));
std_deviation_co = sqrt(sum_co / (N));

The issue is that I am not completely sure if I placed the blocks that calculate the mean and standard deviation in the right part of the code and that's affecting the output. Sometimes I get the output "inf"
Posted
Updated 6-Feb-23 6:21am
v8
Richard MacCutchan 6-Feb-23 7:06am
1. Most of your code is missing.
2. The formulae for both of these can be found at How to Calculate the Mean Value[^].
Auyik 6-Feb-23 7:12am
HI, I just edited my question. Thank you
Richard MacCutchan 6-Feb-23 7:24am
You need to post an actual question? No one is going to go through all that code to try and analyse what it does.
Auyik 6-Feb-23 7:35am
Oh sorry, I deleted that part while editing. The issue is that I am not completely sure if I placed the blocks that calculate the mean and standard deviation in the right part of the code and that's affecting the output
Richard MacCutchan 6-Feb-23 7:38am
As I said, you need to ask a specific question. You should be able to tell if you placed that code in "the right place", by running tests and checking the results. Looking (briefly)at your code I would say it could be improved by moving more code out of main and into separate functions. That way it is much easier to test individual parts of the application.

Solution 1

Quote:
Basically, I get "inf" outputs for the standard deviation

And there isn't anything we can do about that - we don't have your data so we can't duplicate exactly what you are doing. And that's step one in debugging!

Basically, compiling does not mean your code is right! :laugh:
Think of the development process as writing an email: compiling successfully means that you wrote the email in the right language - English, rather than German for example - not that the email contained the message you wanted to send.

So now you enter the second stage of development (in reality it's the fourth or fifth, but you'll come to the earlier stages later): Testing and Debugging.

Start by looking at what it does do, and how that differs from what you wanted. This is important, because it give you information as to why it's doing it. For example, if a program is intended to let the user enter a number and it doubles it and prints the answer, then if the input / output was like this:
Input   Expected output    Actual output
1            2                 1
2            4                 4
3            6                 9
4            8                16
Then it's fairly obvious that the problem is with the bit which doubles it - it's not adding itself to itself, or multiplying it by 2, it's multiplying it by itself and returning the square of the input.
So with that, you can look at the code and it's obvious that it's somewhere here:
C#
private int Double(int value)
{
return value * value;
}

Once you have an idea what might be going wrong, start using the debugger to find out why. Put a breakpoint on the first line of the method, and run your app. When it reaches the breakpoint, the debugger will stop, and hand control over to you. You can now run your code line-by-line (called "single stepping") and look at (or even change) variable contents as necessary (heck, you can even change the code and try again if you need to).
Think about what each line in the code should do before you execute it, and compare that to what it actually did when you use the "Step over" button to execute each line in turn. Did it do what you expect? If so, move on to the next line.
If not, why not? How does it differ?
Hopefully, that should help you locate which part of that code has a problem, and what the problem is.
This is a skill, and it's one which is well worth developing as it helps you in the real world as well as in development. And like all skills, it only improves by use!

Auyik 6-Feb-23 9:31am
Thank you, I edited this post and paste a shorter version of the original code. I assigned to arrays the number of CO's and O's to storage the number of molecules trapped in the surface, then the blocks that calculate the mean and standard deviation where place outside the while loop.

As results, for the mean I get exactly the number of CO trapped. The same for O. Also, I think now the code gives me reasonable results for the corresponding standard deviations.

I'm gonna add again the interactions between the molecules to see how those results change.
Andre Oosthuizen 6-Feb-23 10:00am
What a properly explained in laymen terms solution should look like, my thumbs up!

Solution 2

What you are doing is not the way I would recommend that you do it. You have essentially spread the code out. I would make one function that calculates the mean and standard deviation of a set of data. You can return one of those values from the function and the other one should be passed in as a pointer. Here is what that function could look like as derived from your existing code :
C
double Square( double value )
{
return value * value;
}

// returns standard deviation

double CalcStdDevMean( double data[], int count, double * pMean )
{
double sum = 0;
double stddev = 0;

// calculate mean

for (int k = 0; k < count; k++) {
sum += data[k];
}

* pMean = sum / (double) count;   // save mean value

// calculate standard deviation

sum = 0;   // NOTE: your code is missing this statement.

for (int k = 0; k < count; k++) {
sum += Square( data[k] - mean );
}

stddev = sqrt( sum / (double) count );
return stddev;
}
Now you have all of your calculations in one function so any errors in it can be corrected in one place. As I noted in the function's code, your error was the sum was not cleared before computing the standard deviation.

Here is how you would call this function :
C
std_deviation_o   = CalcStdDevMean( num_o, N, & average_o );
std_deviation_co  = CalcStdDevMean( num_co, N, & average_co );
std_deviation_co2 = CalcStdDevMean( num_co2, N, & average_co2 );
This makes your code much easier to understand and maintain.

v2