First Program

M

mwt

Fred said:
Now the OP might want to consider these two variations of his program:
1) Find the mean value (sum divided by size) of the items in the array.
2) What might happen if the array is real numbers instead of integers?

In (1), obviously the mean is unlikely to be an exact integer, so the answer
should be stated as a double. So his summation function, to become a
mean() method, might looks like:
double compute_mean( int *array, int size );
or for (2):
double compute_mean( double *array, int size );

Here's a new function to compute the mean. In the main function, I've
precluded "0" as valid input in order to get around the divide by zero
problem. The cast to double in the return statement seems to be
necessary to make it work, but I don't know if this is the best way to
approach it.

double compute_mean(int *arr, int arr_length)
{
int j;
int total = 0;
for(j = 0; j < arr_length; j++)
{
total += arr[j];
}
return (double) total / arr_length;

}
 
K

Keith Thompson

mwt said:
Keith Thompson wrote: [...]
What happens if the user enters "0"? Or "-123"?

I think the new code I wrote addresses these issues. Now, if the user
inputs non-digits, the program exits (not the best way to handle
things, but at least it works). I think that "0" is a valid digit to
input in this case, so I allow it. Certainly negative numbers would be
interesting to be able to process properly, although I'm not sure how
to go about it.

You probably don't want to allow length to be 0. C doesn't support
zero-sized objects. In particular, if length==0, you call malloc(0),
which can yield either NULL or a valid pointer to some (unusable)
chunk of allocated memory. Since you don't actually access the array
in that case,n it's not a real problem, but it's probably better to
avoid it altogether.

[snip]
sc = sscanf(c, "%d", &length);
if(sc > 0 && length >=0)
[snip]

sscanf() returns the number of input items assigned. It would be a
bit clearer, I think, to check that it returns exactly the number
of items you expected:

if (sc == 1 && length > 0)

This is more easily extended to reading multiple items:

sc = sscanf(c, "%d%d", &x, &y);
if (sc == 2) {
/* got both items */
}
else {
/* an error occurred */
}
 
K

Keith Thompson

mwt said:
Here's a new function to compute the mean. In the main function, I've
precluded "0" as valid input in order to get around the divide by zero
problem. The cast to double in the return statement seems to be
necessary to make it work, but I don't know if this is the best way to
approach it.

double compute_mean(int *arr, int arr_length)
{
int j;
int total = 0;
for(j = 0; j < arr_length; j++)
{
total += arr[j];
}
return (double) total / arr_length;

}

Yes, this is one of the few cases where a cast is justified.

Without it (as you've probably seen), the expression "total / arr_length"
is evaluated as an int, which means the result is truncated. The "/"
operator takes two operands of the *same* numeric type, and yields a
result of the same type. Converting one operand to double forces the
other operand to be implicitly converted to double, yielding a double
result.

For the sake of symmetry, I might cast both operands:

return (double)total / (double)arr_length;

but it makes no real difference.
 
F

Fred Kleinschmidt

mwt said:
Fred said:
Now the OP might want to consider these two variations of his program:
1) Find the mean value (sum divided by size) of the items in the array.
2) What might happen if the array is real numbers instead of integers?

In (1), obviously the mean is unlikely to be an exact integer, so the
answer
should be stated as a double. So his summation function, to become a
mean() method, might looks like:
double compute_mean( int *array, int size );
or for (2):
double compute_mean( double *array, int size );

Here's a new function to compute the mean. In the main function, I've
precluded "0" as valid input in order to get around the divide by zero
problem. The cast to double in the return statement seems to be
necessary to make it work, but I don't know if this is the best way to
approach it.

double compute_mean(int *arr, int arr_length)
{
int j;
int total = 0;
for(j = 0; j < arr_length; j++)
{
total += arr[j];
}
return (double) total / arr_length;

}
The above code wil definitely have problems finding the mean of this array:
int values[4] = {MAXINT, MAXINT, (MAXINT-2), (MAXINT-2)};
The actual value is (MAXINT-1), which is representable. But the above code
will overflow.
So a safer code is:
double compute_mean(int *arr, int arr_length)
{
int j;
double total = 0.0;
for(j = 0; j < arr_length; j++)
{
total += (double)arr[j]/arr_length;
}
return total;
}

However, it is quite inefficient for most arrays, and will encounter a lot
of
roundoff and/or truncation error.
There are other ways to program it so that it is much more efficient
and has a minimal roundoff error. One way is to accumulate the integer sum
until the next addition would overflow, then divide that sum by arr_length,
and keep adding these partial means together.

However, even that is not sufficient if the magnitudes of values in the
array
differ greatly. Try adding 10e-18 to 1.0 and see what the result is.
But what if there are 100000000 values of 10e-18 in the array, and one
value of 1.0? The order of summation is important.
 
V

Vladimir S. Oka

Fred Kleinschmidt opined:
mwt said:
Fred said:
Now the OP might want to consider these two variations of his
program: 1) Find the mean value (sum divided by size) of the items
in the array. 2) What might happen if the array is real numbers
instead of integers?

In (1), obviously the mean is unlikely to be an exact integer, so
the answer
should be stated as a double. So his summation function, to become
a mean() method, might looks like:
double compute_mean( int *array, int size );
or for (2):
double compute_mean( double *array, int size );

Here's a new function to compute the mean. In the main function,
I've precluded "0" as valid input in order to get around the divide
by zero problem. The cast to double in the return statement seems to
be necessary to make it work, but I don't know if this is the best
way to approach it.

double compute_mean(int *arr, int arr_length)
{
int j;
int total = 0;
for(j = 0; j < arr_length; j++)
{
total += arr[j];
}
return (double) total / arr_length;

}
The above code wil definitely have problems finding the mean of this
array: int values[4] = {MAXINT, MAXINT, (MAXINT-2), (MAXINT-2)};

You surely mean INT_MAX from said:
The actual value is (MAXINT-1), which is representable. But the above
code will overflow.
So a safer code is:
double compute_mean(int *arr, int arr_length)
{
int j;
double total = 0.0;
for(j = 0; j < arr_length; j++)
{
total += (double)arr[j]/arr_length;
}
return total;
}

However, it is quite inefficient for most arrays, and will encounter
a lot of
roundoff and/or truncation error.
There are other ways to program it so that it is much more efficient
and has a minimal roundoff error. One way is to accumulate the
integer sum until the next addition would overflow, then divide that
sum by arr_length, and keep adding these partial means together.

However, even that is not sufficient if the magnitudes of values in
the array
differ greatly. Try adding 10e-18 to 1.0 and see what the result is.
But what if there are 100000000 values of 10e-18 in the array, and
one value of 1.0? The order of summation is important.

--
Now it's time to say goodbye
To all our company...
M-I-C (see you next week!)
K-E-Y (Why? Because we LIKE you!)
M-O-U-S-E.

<http://clc-wiki.net/wiki/Introduction_to_comp.lang.c>
 
M

Micah Cowan

Keith Thompson said:
mwt said:
Here's a new function to compute the mean. In the main function, I've
precluded "0" as valid input in order to get around the divide by zero
problem. The cast to double in the return statement seems to be
necessary to make it work, but I don't know if this is the best way to
approach it.

double compute_mean(int *arr, int arr_length)
{
int j;
int total = 0;
for(j = 0; j < arr_length; j++)
{
total += arr[j];
}
return (double) total / arr_length;

}

Yes, this is one of the few cases where a cast is justified.

Without it (as you've probably seen), the expression "total / arr_length"
is evaluated as an int, which means the result is truncated. The "/"
operator takes two operands of the *same* numeric type, and yields a
result of the same type. Converting one operand to double forces the
other operand to be implicitly converted to double, yielding a double
result.

For the sake of symmetry, I might cast both operands:

return (double)total / (double)arr_length;

but it makes no real difference.

Even if I decided to cast just the left operand, I'd at least want to
bring the cast closer to the expression I'm converting, as you have
done, to make it clearer... the original statement seems liable to be
misread as symantically equivalent to (double(total / arr_length)
 
K

Keith Thompson

Micah Cowan said:
Even if I decided to cast just the left operand, I'd at least want to
bring the cast closer to the expression I'm converting, as you have
done, to make it clearer... the original statement seems liable to be
misread as symantically equivalent to (double(total / arr_length)

You missed a right parenthesis;

(double)(total / arr_length)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,176
Messages
2,570,950
Members
47,503
Latest member
supremedee

Latest Threads

Top