470,826 Members | 1,998 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,826 developers. It's quick & easy.

computing average value

I'm trying to get average value. My first attempt is:

#include <...>

template <typename T>
struct avg : public unary_function<T, void>
{
T sum, count;
avg() : sum(0), count(0) {}
void operator()(T value) { sum+=value; ++count; }
T result() { return sum / count; }
};

int main()
{
const int N = 4;
double arr[N] = { 1, 2, 3, 4 };
avg<double> res = std::for_each(arr, arr+N, avg<double>());
std::cout << "avg=" << res.result() << std::endl;
}

Questions are:
1. Is for_each a right way? May be I should use accumulate or
something?
2. ": public unary_function<T, void>" is not nessesary. Should I use it
anyway?

Raider

Feb 26 '06 #1
5 2065
"Raider" <sr*****@yandex.ru> wrote in message
news:11**********************@z34g2000cwc.googlegr oups.com...
: I'm trying to get average value. My first attempt is:
:
: #include <...>
:
: template <typename T>
: struct avg : public unary_function<T, void>
: {
: T sum, count;
: avg() : sum(0), count(0) {}
: void operator()(T value) { sum+=value; ++count; }
: T result() { return sum / count; }
: };
:
: int main()
: {
: const int N = 4;
: double arr[N] = { 1, 2, 3, 4 };
: avg<double> res = std::for_each(arr, arr+N, avg<double>());
: std::cout << "avg=" << res.result() << std::endl;
: }
:
: Questions are:
: 1. Is for_each a right way? May be I should use accumulate or
: something?

I have to say that my first instinct would be to use (in main):
double avg = std::accumulate( arr, arr+N, 0 ) / N;
Only if the item count is unknown would you need a special class.

I think that a problem with for_each is that you have no
guarantee that the algorithm won't create copies of the
provided function object.
So std::accumulate would be safer. You could eventually use
a custom predicate, and an accumulation value of type
std::pair<double,unsigned> -- sum and count -- or similar.

: 2. ": public unary_function<T, void>" is not nessesary.
: Should I use it anyway?
It is probably a good habit to take, as it will be useful for
some more advanced generic programming techniques.
hth -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Feb 26 '06 #2
Ivan Vecerina wrote:
"Raider" <sr*****@yandex.ru> wrote in message
news:11**********************@z34g2000cwc.googlegr oups.com...
: I'm trying to get average value. My first attempt is:
:
: #include <...>
:
: template <typename T>
: struct avg : public unary_function<T, void>
: {
: T sum, count;
: avg() : sum(0), count(0) {}
: void operator()(T value) { sum+=value; ++count; }
: T result() { return sum / count; }
: };
:
: int main()
: {
: const int N = 4;
: double arr[N] = { 1, 2, 3, 4 };
: avg<double> res = std::for_each(arr, arr+N, avg<double>());
: std::cout << "avg=" << res.result() << std::endl;
: }
:
: Questions are:
: 1. Is for_each a right way? May be I should use accumulate or
: something?

I have to say that my first instinct would be to use (in main):
double avg = std::accumulate( arr, arr+N, 0 ) / N;
Only if the item count is unknown would you need a special class.

I think that a problem with for_each is that you have no
guarantee that the algorithm won't create copies of the
provided function object.


My understanding of the standard is that this guarantee actually is made:

[25.1.1]

template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
Effects: Applies f to the result of dereferencing every iterator in the
range [first, last), starting from first and proceeding to
last - 1.
Returns: f.
Complexity: Applies f exactly last - first times.
Notes: If f returns a result, the result is ignored.

As I read this paragraph, "f" denotes the function object passed. The only
copy that is made is in passing the object by value. Other than that, you
should be safe. Besides:

(a) If copies were to be made, the return of f would not make sense. This
hook is provided to pass back information that the function object may
collect during its pass over the objects in the sequence.

(b) If this is *not* the intended meaning of the standard, that should
qualify as a bug in the standard.
[snip]
Best

Kai-Uwe Bux
Feb 26 '06 #3
"Kai-Uwe Bux" <jk********@gmx.net> wrote in message
news:dt**********@murdoch.acc.Virginia.EDU...
: Ivan Vecerina wrote:
....
: > I think that a problem with for_each is that you have no
: > guarantee that the algorithm won't create copies of the
: > provided function object.
:
: My understanding of the standard is that this guarantee actually is
made:
:
: [25.1.1]
:
: template<class InputIterator, class Function>
: Function for_each(InputIterator first, InputIterator last, Function f);
: Effects: Applies f to the result of dereferencing every iterator in the
: range [first, last), starting from first and proceeding to
: last - 1.
: Returns: f.
: Complexity: Applies f exactly last - first times.
: Notes: If f returns a result, the result is ignored.
:
: As I read this paragraph, "f" denotes the function object passed. The
only
: copy that is made is in passing the object by value. Other than that,
you
: should be safe.

Right -- I'm afraid that I confused for_each with other algorithms.
for_each
is actually the one that provides the most guarantees regarding side
effects
and order of execution. See for example the following discussion:
http://www.angelikalanger.com/Articl...Transform.html
Thank you for the correction,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Feb 26 '06 #4
In article <11**********************@z34g2000cwc.googlegroups .com>,
"Raider" <sr*****@yandex.ru> wrote:
I'm trying to get average value. My first attempt is:

#include <...>

template <typename T>
struct avg : public unary_function<T, void>
{
T sum, count;
'sum' above probably shouldn't be of type T
avg() : sum(0), count(0) {}
void operator()(T value) { sum+=value; ++count; }
T result() { return sum / count; }
};

int main()
{
const int N = 4;
double arr[N] = { 1, 2, 3, 4 };
avg<double> res = std::for_each(arr, arr+N, avg<double>());
std::cout << "avg=" << res.result() << std::endl;
}

Questions are:
1. Is for_each a right way? May be I should use accumulate or
something?
Although for_each works, I'd be inclined to use accumulate. What you are
doing is accumulating the total of the items and the number of items,
then doing a divide on them...

template < typename T >
pair<T, int> avg_accum( const std::pair<T, int>& prev, T next )
{
return make_pair( prev.first + next, prev.second + 1 );
}

pair< double, int > p = accumulate( arr, arr + N, make_pair( 0.0, 0 ),
&avg_accum<double> );
cout << "avg2 = " << (p.first/p.second) << '\n';
Of course in your particular case, you already know the number of items
so you could just use the specialized form of accumulate, but the above
will even work for input iterators, whereas the specialized form would
not.

2. ": public unary_function<T, void>" is not nessesary. Should I use it
anyway?


I think it's good to be in the habit of using them, it communicates
intent, and is useful for functor composition.
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 26 '06 #5
> 'sum' above probably shouldn't be of type T

I think it must be as follows:

typename T sum;
int count;

And thanks for the rest feedback!

Raider

Feb 27 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Tony Lennard | last post: by
5 posts views Thread by Carlo B | last post: by
3 posts views Thread by C++Geek | last post: by
21 posts views Thread by Bill Cunningham | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.