In other words, suppose n is 3 and the numbers are 1, 2, and 3. Then the average is 2. The squares of the differences are 1, 0 and 1, so the variance is 2/3.
Suppose n is 3 and the numbers are 10, 5 and 3. The average is 18/3 = 6. The squares of the differences are (10-6)(10-6) = 16, (5-6)(5-6) = 1, and (3-6)(3-6) = 9. Thus, the variance is (16+1+9)/3 = 26/3 = 8.6667.
Ok, now take a few minutes and try to write variance.
Here's the strategy for writing variance
And here's the code (also in variance.c):
#include <stdio.h>
int main(int argc, char **argv)
{
int n, i;
double *values;
double avg;
double variance;
/* First you need to get n from the command line arguments. */
if (argc != 2) {
fprintf(stderr, "usage: variance n\n");
exit(1);
}
n = atoi(argv[1]);
if (n <= 0) exit(1);
/* Next, you need to malloc() space for n doubles. */
values = (double *) malloc(sizeof(double)*n);
/* Next, you read them in using scanf(). */
for (i = 0; i < n; i++) {
if (scanf("%lf", &(values[i])) != 1) exit(1);
}
/* Next, you compute their average. */
avg = 0;
for (i = 0; i < n; i++) {
avg += values[i];
}
avg /= n;
/* Now, you compute the sum of the squares of the differences. */
variance = 0;
for (i = 0; i < n; i++) {
variance += ((values[i]-avg)*(values[i]-avg));
}
/* Finally, you compute the variance and print them both out. */
variance /= n;
printf("Average: %lf\n", avg);
printf("Variance: %lf\n", variance);
return 0;
}
|
It works quite nicely:
UNIX> variance
usage: variance n
UNIX> variance 3
1 2 3
Average: 2.000000
Variance: 0.666667
UNIX> variance 3
1
2 3
Average: 2.000000
Variance: 0.666667
UNIX> variance 3
10
5
3
Average: 6.000000
Variance: 8.666667
UNIX>
We'll solve this by using the fields library instead. We'll read in lines using get_line() and if a line begins with '#', we'll ignore it. If it doesn't, then we'll use sscanf() to turn its fields into double's. The code is in variance2.c. Here is the only change from variance.c:
#include "fields.h"
main(int argc, char **argv)
{
int n, i, j;
IS is;
...
/* Next, you read them in using the fields library. */
is = new_inputstruct(NULL);
i = 0;
while (i < n && get_line(is) >= 0) {
if (is->text1[0] != '#') {
for (j = 0; j < is->NF; j++) {
if (i < n) {
if (sscanf(is->fields[j], "%lf", &(values[i])) != 1) exit(1);
i++;
}
}
}
}
if (i < n) exit(1);
|
Note, I've covered for some common input errors such as not entering a double, and not entering enough numbers. Go over this code until you understand exactly what it is doing. I will expect you to be able to write code like this without problems.
When we run it, we see it works:
UNIX> make variance2 gcc -g -I/home/cs140/include -c variance2.c gcc -g -I/home/cs140/include -o variance2 variance2.o /home/cs140/objs/fields.o UNIX> variance2 3 1 2 3 Average: 2.000000 Variance: 0.666667 UNIX> variance2 3 1 2 Frog UNIX> variance2 3 10 # Hi!!!! 5 3 Average: 6.000000 Variance: 8.666667 UNIX>Note, when I typed Frog, it exited, because sscanf() returned zero.