averages

B

Bill Cunningham

I want to write a function that takes several doubles to average with an
int. An arithmetic mean, exponential mean and geometric mean to get started.
These are my prototypes.

double Sma (double *,int); /*arithmetic mean */
double Ema (double *, int); /* exponential mean */

Bill
 
L

Lew Pitcher

I want to write a function that takes several doubles to average with an
int.

What do you mean "to average with an int"?
An arithmetic mean, exponential mean and geometric mean to get
started. These are my prototypes.

double Sma (double *,int); /*arithmetic mean */
double Ema (double *, int); /* exponential mean */

Nice prototypes.

I'm not certain of the reason you posted this note. Is it to tell us
something about yourself ("I want to write") or is it to ask us a question
(i.e. "How do I write ...?")? You might want to clarify this before
proceeding.

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
B

Bill Cunningham

Nice prototypes.

I'm not certain of the reason you posted this note. Is it to tell us
something about yourself ("I want to write") or is it to ask us a question
(i.e. "How do I write ...?")? You might want to clarify this before
proceeding.

Ok Lew I use the double * for this -

12.96+13.21+14

The int is to divide the sum of the above numbers by. In this case the int
would be 3. I suppose I wouldn't have to do it like this, the function could
count for me and determine its own int value.

My real concern is the first parameter. Is the double * the right way to
go? To pass several doubles to the function ?

double Sma (double *numbers)
{
...}

Now I need to keep track somehow to the number of number entered here. In
the above case that would be numbers[0], numbers[1], and numbers[3]. How
would I set up a counting mechanism in C to count 3, 15,20 ,150 or however
many numbers[n] there is?

Does this help?

Bill
 
T

Tim Harig

Now I need to keep track somehow to the number of number entered here. In
the above case that would be numbers[0], numbers[1], and numbers[3]. How
would I set up a counting mechanism in C to count 3, 15,20 ,150 or however
many numbers[n] there is?

The question is not how to keep track of the quantity of numbers entered
but how you are managing your memory as the numbers are input. Memory
management is a large topic with many different solutions that are
optimized for many different problems. A simple singly-linked list should
work well for what you are trying to do:

http://en.wikipedia.org/wiki/Linked_list
 
L

Lew Pitcher

Nice prototypes.

I'm not certain of the reason you posted this note. Is it to tell us
something about yourself ("I want to write") or is it to ask us a
question (i.e. "How do I write ...?")? You might want to clarify this
before proceeding.

Ok Lew I use the double * for this -

12.96+13.21+14

The int is to divide the sum of the above numbers by. In this case the int
would be 3. I suppose I wouldn't have to do it like this, the function
could count for me and determine its own int value.

My real concern is the first parameter. Is the double * the right way
to
go? To pass several doubles to the function ?

double Sma (double *numbers)
{
...}

Now I need to keep track somehow to the number of number entered here. In
the above case that would be numbers[0], numbers[1], and numbers[3]. How
would I set up a counting mechanism in C to count 3, 15,20 ,150 or however
many numbers[n] there is?

Does this help?

Yes, thank you.

OK, so you use the integer argument to denote the number of doubles being
passed through the double * argument. That's cool.

You ask if
double *
is the right way to pass several doubles to the function.

Yes, you can use either
double *list
or
double list[]
this way. As /function argument list specifiers/, they both mean the same
thing. The function will receive a pointer-to-double which it can then use
as a pointer to the first element of an array of doubles.

Within the body of the function, you can access elements of this array
either through pointer arithmetic
*(list + element_number)
or through array subscripting
list[element_number]


BTW, my original question was prompted because I misread your prototypes.
Sorry for that.

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
B

Barry Schwarz

I want to write a function that takes several doubles to average with an
int. An arithmetic mean, exponential mean and geometric mean to get started.
These are my prototypes.

double Sma (double *,int); /*arithmetic mean */
double Ema (double *, int); /* exponential mean */

Here is the same advice Nick sent regarding your previous project:

"do you know hoe to solve this problem with pencil and paper and a
calculator?

If you don't you won't be able to program it."

Since the phrase "exponential mean" has no meaning except for
exponential distributions, odds are your prototype for Ema is not what
you want.

I wonder why you did not provide a prototype for geometric mean.

I wonder why you called the arithmetic mean function Sma and not Ama.

I wonder why you posted this at all since you didn't ask a question or
post code for review.
 
B

Bill Cunningham

*HOW* will the function count for you and determine its own int
value? If you pass an integer count of the number of doubles to
average, that's fine, it will work great. Beware, though, that you
can't check whether the integer passed is a lie or not. If you
don't pass in a count, how are you going to figure out when you've
hit the end?
[snip]

The m in Sma() and Ema() means "moving" as in a moving average. So if my
second parameter int count for example is 12, and 15 numbers are in the list
the 3 oldest are to be eliminated or atleast put somewhere in a file or
something for safekeeping and dropped from the average. That's how I would
know that I've hit the "end". As a 13th number is added to the beginning,
the 1st or oldest value is removed from the average. Just something more I
guess to complicate my life.

Bill
 
B

Bill Cunningham

So how does your function *KNOW* that 15 numbers are in the list?

That's the big question. I don't know. This is in idea stage at this
time. I am writing prototypes in a header right now.
If you're passing a "double *" to the function, it can't be a linked
list. Is the double after the last number that counts set to -1776.0
as a marker?

Any negative number would do. Even -1 that some functions return on
failure.

Bill
 
K

Keith Thompson

Bill Cunningham said:
Gordon Burditt said:
*HOW* will the function count for you and determine its own int
value? If you pass an integer count of the number of doubles to
average, that's fine, it will work great. Beware, though, that you
can't check whether the integer passed is a lie or not. If you
don't pass in a count, how are you going to figure out when you've
hit the end?
[snip]

The m in Sma() and Ema() means "moving" as in a moving average. So if my
second parameter int count for example is 12, and 15 numbers are in the list
the 3 oldest are to be eliminated or atleast put somewhere in a file or
something for safekeeping and dropped from the average. That's how I would
know that I've hit the "end". As a 13th number is added to the beginning,
the 1st or oldest value is removed from the average. Just something more I
guess to complicate my life.

If count is 12, how will your function know that there are 15 numbers
in the list?
 
B

Bill Reid

Barry Schwarz said:
Here is the same advice Nick sent regarding your previous project:

"do you know hoe to solve this problem with pencil and paper and a
calculator?

If you don't you won't be able to program it."
Who you calling a "hoe"?
Since the phrase "exponential mean" has no meaning except for
exponential distributions, odds are your prototype for Ema is not what
you want.

I wonder why you did not provide a prototype for geometric mean.

I wonder why you called the arithmetic mean function Sma and not Ama.
I, in my borderline mystical way, know the answers to all these questions,
based on his previous posts, and my knowledge of the particular type of
software
he's TRYING to write (been TRYING to write for what? seven years now?)...and
I hardly even read this group...
I wonder why you posted this at all since you didn't ask a question or
post code for review.
I thought he wanted somebody like me who can read his mind to
fill in the code for his prototypes...

Anyway, I won't do that, but he should proceed from the reading
of the data from his "database" forward through malloc'ing an array of
doubles, the size of which is stored as that int he has in his prototype.
Then he can proceed to call his averaging functions, since he will
have MOST of what he needs to calculate the various averages...

What he REALLY wants to do, REALLY, is set up a structure that
includes the number of doubles in the array, and a pointer to the array
(as a bare minimum to solve the problem). He checks his database
to see how many of the double fields he CAN read into memory (then,
IDEALLY, compares this to how many he WANTS to read into
memory for any particular operation he may want to perform), THEN
he malloc's the array and writes the number of items to be read
into the array into the int member of the structure, AND THEN
he reads the "database" (such as it is) double fields into the array
(except, REALLY, he wants an array of "time series" structs that
include the date "key" field that corresponds to each double field),
THEN he is now ready to start performing all kinds of operations
on that time range of data...assuming he actually has enough data
to perform the desired operation in the first place; for example, it's
impossible to find the average of 200 doubles when in fact you
only have 150 double fields in the "database", so in THAT case, you
might want to spit the fact that it is impossible to perform the
operation back at the user or really the requesting module due
to "INSUFFICIENT DATA"...

Yeah, you're right, if you can do it with paper and pencil, it's easy
to do it in software...
 
T

Tim Harig

You should have told us from the beginning that you only wanted a running
total. It makes a *HUGE* difference in your design. Again I would suggest
using data structures rather the arrays. For a running average, a
doubly-linked array data structure would be ideal.

I already posted a example of using a singly linked data structure to
find a simple average. It could easily be modified to calculate your
running average if you also modify it to used a doubly linked list.
something for safekeeping and dropped from the average. That's how I would
know that I've hit the "end". As a 13th number is added to the beginning,
the 1st or oldest value is removed from the average. Just something more I
guess to complicate my life.

If you want to use arrays Use a standard average function but trim the
input to include. Something like (psuedo code):

/*
from a array of total_count elements, return a pointer to last wanted_count
element from the end -- returns NULL if not enough elements are available
*/
double* tail(double* data, int total_count, int wanted_count);

/*
from a data array of count number of elements, retrn the average
*/
double average(double* data, int count);

/* same argument definition as tail() */
double Sma(double* data, int total_count, int wanted_count) {
new_set = tail(data, total_count, wanted_count)
if (new_set == NULL) {
global_error_flag = ERROR;
return whatever_invalid_unable_to_indentify_as_worthless;
}
return average(new_set, wanted_count);
}

Note that you will have to define some kind of error handling system as you
cannot indicate errors using doubles.
That's the big question. I don't know. This is in idea stage at this
time. I am writing prototypes in a header right now.

The bottom line is that you are leaping without a clue of what you are
doing right now. Stop, clarify what you are doing, listen to
what people are telling you, then think again. Only then should you act.

A. Assuming you are using an array or singly linked list -- not a doubly
linked list -- you have to tell it where to find the first point, how
may datapoints you are passing to it, where to find the first datapoint you
want tabulated, and how many elements you want tabulated. Then you *MUST*
give it exactly what you told it you would give it or you can cause an
overun.

If you pass it a doubly linked list, then it can find the data locations
and the limits of the dataset for itself. I have already posted a simple
average routine using a singly linked list before I realized you wanted a
running average. I could be modified easily enough to calculate a running
average if you modify it to use doubly linked lists for your data
structure.

Where did the -1776.0 come from? I didn't see it in the thread?
Any negative number would do. Even -1 that some functions return on
failure.

I am not sure what this is in reponse to?

If you are thinking of passing -1 to a function as a pointer then you
are in error as pointers are unsigned and using a constant to a pointer
is insane. If you are thinking as passing it along as a double, then
how will you determine whether a -1 is valid data or an error?

Functions which pass -1 can do so only because they have elimited negative
numbers as valid data. Doing so is usually a sign of poor design even
when it is possible (see _Code Complete_ by Steve McConnell and _Writing
Solid Code_ by Steve Maguire).
 
C

Chris M. Thomasson

Bill Cunningham said:
I want to write a function that takes several doubles to average with
an int. An arithmetic mean, exponential mean and geometric mean to get
started. These are my prototypes.

double Sma (double *,int); /*arithmetic mean */
double Ema (double *, int); /* exponential mean */
___________________________________________________________________
#include <stdio.h>


#define DEPTH(a) (sizeof(a) / sizeof(*a))


double
calc_and_output_avg(
double* const self,
size_t depth,
FILE* file
) {
if (depth) {
size_t i;
double total = 0;
fputc('{', file);
for (i = 0; i < depth; ++i) {
total += self;
if (i + 1 < depth) {
fprintf(file, "%f, ", self);
} else {
fprintf(file, "%f} has an average of ", self);
}
}
fprintf(file, "%f\n", total / depth);
return total / depth;
}
return 0;
}


int main(void) {
double x[] = { 1.6, 4.3, 6.1, 0.6 };
double y[] = { 4.5, 14.3 };
double z[] = { 3.5, 6.9, 2.6 };
calc_and_output_avg(x, DEPTH(x), stdout);
calc_and_output_avg(y, DEPTH(y), stdout);
calc_and_output_avg(z, DEPTH(z), stdout);
return 0;
}
___________________________________________________________________
 
C

Chris M. Thomasson

[...]

or maybe something like:
___________________________________________________________________
#include <stdio.h>


#define DEPTH(a) (sizeof(a) / sizeof(*a))


double
calc_and_output_avg(
double* const self,
size_t depth,
FILE* file
) {
if (depth) {
size_t i;
double total = 0;
if (file) fputc('{', file);
for (i = 0; i < depth; ++i) {
total += self;
if (file) {
if (i + 1 < depth) {
fprintf(file, "%f, ", self);
} else {
fprintf(file, "%f} has an average of ", self);
}
}
}
if (file) fprintf(file, "%f\n", total / depth);
return total / depth;
}
return 0;
}


int main(void) {
double x[] = { 1.6, 4.3, 6.1, 0.6 };
double y[] = { 4.5, 14.3 };
double z[] = { 3.5, 6.9, 2.6 };
calc_and_output_avg(x, DEPTH(x), stdout);
calc_and_output_avg(y, DEPTH(y), stdout);
calc_and_output_avg(z, DEPTH(z), stdout);
printf("%f\n", calc_and_output_avg(x, DEPTH(x), NULL));
printf("%f\n", calc_and_output_avg(y, DEPTH(y), NULL));
printf("%f\n", calc_and_output_avg(z, DEPTH(z), NULL));
return 0;
}
___________________________________________________________________


;^)
 
B

Bill Cunningham

You should have told us from the beginning that you only wanted a running
total. It makes a *HUGE* difference in your design.

Oh I see. I didn't realize.

Again I would suggest
using data structures rather the arrays. For a running average, a
doubly-linked array data structure would be ideal.

I already posted a example of using a singly linked data structure to
find a simple average. It could easily be modified to calculate your
running average if you also modify it to used a doubly linked list.
[snip]

I am kinda struggling with binary search trees right now. Do you think
that design could be implemented into this. I realize too malloc is going to
be needed with the sizeof operator.
 
T

Tim Harig

I am kinda struggling with binary search trees right now. Do you think
that design could be implemented into this. I realize too malloc is going to
be needed with the sizeof operator.

You can do just about anything with just about anything if you are will to
try hard enough. The question, therefore, is not *can* something be done
but *should* something be done. All data structures have their own
strengths and weaknesses.

I chose linked lists because they are simple and they are conceptualy
close to what you are trying to do. Linked lists are conceptually
similar to arrays except that they make memory management easier.
They can grow or shrink at will and they can mark their own bounds so
as to prevent overuns.

If you don't need more then the last few entries of the array and can
affort to throw away old data, then you might also consider working with a
linked list formed int a circle. Then you don't have to constantly worry
about find the last few elements in the list. It word work a little like
working around a wrapping shift register.

Skip lists would also be nice to make finding the element numbers that you
want very quick. The look almost like simple linked lists; but, may make
searching much faster. If you give every link an ordinal number then skip
lists would make finding the last 15 elements extremely quick even for
large lists. William Pugh's "Skip Lists: A Probablistic Alternative to
Balanced Trees" is an excellent read. There are several excellent
libraries for working with skip lists available on the Web.

A tree structure removes you conceptually from your problem; but, if you
see a natural paradigm that you can use which keeps things clear, then by
all means use them. Don't just use them because they are the only data
structure that you are familiar with and don't assume that a more
complicated data structure is going to be significantly faster enough to
make the extra complication worth while until you have tried the simpler
solution and found it to be underperforming.

Basically keep your head and use what you think will suit the problem best.
 
D

Doug Miller

You should have told us from the beginning that you only wanted a running
total. It makes a *HUGE* difference in your design.

Oh I see. I didn't realize.

Again I would suggest
using data structures rather the arrays. For a running average, a
doubly-linked array data structure would be ideal.

I already posted a example of using a singly linked data structure to
find a simple average. It could easily be modified to calculate your
running average if you also modify it to used a doubly linked list.
[snip]

I am kinda struggling with binary search trees right now. Do you think
that design could be implemented into this. I realize too malloc is going to
be needed with the sizeof operator.
I think you need to take a couple deep breaths, relax, sit down, and spend
some time -- thirty minutes or more, not just a couple minutes -- really
thinking about exactly what problem you're trying to solve.
 
B

Barry Schwarz

You should have told us from the beginning that you only wanted a running
total. It makes a *HUGE* difference in your design.

Oh I see. I didn't realize.

Again I would suggest
using data structures rather the arrays. For a running average, a
doubly-linked array data structure would be ideal.

I already posted a example of using a singly linked data structure to
find a simple average. It could easily be modified to calculate your
running average if you also modify it to used a doubly linked list.
[snip]

I am kinda struggling with binary search trees right now. Do you think
that design could be implemented into this. I realize too malloc is going to
be needed with the sizeof operator.

Well done Bill. You started implying a very simple problem, got a
bunch of people including me to bite, and now have moved on to moving
averages, deleting "obsolete" data, saving the obsolete data in a
file, binary search trees, malloc, and sizeof. And you did this
without ever telling us what you really wanted to do.

Congratulations. One of your best troll baits in years.
 
T

Thomas Matthews

Bill said:
I want to write a function that takes several doubles to average with an
int. An arithmetic mean, exponential mean and geometric mean to get started.
These are my prototypes.

double Sma (double *,int); /*arithmetic mean */
double Ema (double *, int); /* exponential mean */

Bill
I would change the prototypes:
double Arithmetic_Moving_Average(double * input_data,
unsigned int quantity);
double Exponential_Moving_Average(double * input_data,
unsigned int quantity);

I really, really, hate acronyms and abbreviations, especially
when having to maintain software. Also, since quantities are
usually not negative, an unsigned int, would help provide
compile-time checking (which is a lot more helpful than trying
to find issues during run-time).

Also, the difference in compilation times between using
acronyms and abbreviations is highly negligible compared
to using long descriptive names. There is no difference
in the executable times. HOWEVER, the time required to
decipher "Sma" is a lot longer than "Arithmetic_Moving_Average"
or "ArithmeticMovingAverage".

Try using a lot of comments to describe the process as you
are coding. I find this helps me work out the understanding
and also gives me insight when I look back at the code
after a couple of days on a different project (or being
distracted).

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library
 
T

Thad Smith

Thomas said:
I would change the prototypes:
double Arithmetic_Moving_Average(double * input_data,
unsigned int quantity);
double Exponential_Moving_Average(double * input_data,
unsigned int quantity);

I like putting meaningful names on functions and parameters, but in what
sense do the proposed functions perform a moving average?
Also, the difference in compilation times between using
acronyms and abbreviations is highly negligible compared
to using long descriptive names. There is no difference
in the executable times. HOWEVER, the time required to
decipher "Sma" is a lot longer than "Arithmetic_Moving_Average"
or "ArithmeticMovingAverage".

I agree for external function names. The further away they are defined,
the more descriptive should be their names. For very local variables i
and j are fine.
Try using a lot of comments to describe the process as you
are coding. I find this helps me work out the understanding
and also gives me insight when I look back at the code
after a couple of days on a different project (or being
distracted).

I agree. In my opinion, the most important comments are on variables,
describing what data is being represented, including units where
appropriate. If you understand the data, figuring out the associated
processing is usually easy.
 
T

Tim Harig

I agree for external function names. The further away they are defined,
the more descriptive should be their names. For very local variables i
and j are fine.

I have debugged too many pieces of code where variables x,y,i,j,k have
caused bugs. Its far too easy to confuse them and it doesn't take any more
effort to use more descriptive names.

int sequence_index;
int current_object;
etc.

In theory very small functions should be clear even with single char names.
The problem is that simple functions turn into larger functions and people
don't bother to make better variable names as they go. Sooner or later,
somebody mixes up an i and an a j. (see Steve McConnell, _Code Complete_
Chapter 15.2, section "Using Loop Variables")

It is much less effort to do the right thing from the beginning.
 

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

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,133
Latest member
MDACVReview
Top