computing average value

Discussion in 'C++' started by Raider, Feb 26, 2006.

  1. Raider

    Raider Guest

    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
    Raider, Feb 26, 2006
    #1
    1. Advertising

  2. "Raider" <> wrote in message
    news:...
    : 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
    Ivan Vecerina, Feb 26, 2006
    #2
    1. Advertising

  3. Raider

    Kai-Uwe Bux Guest

    Ivan Vecerina wrote:

    > "Raider" <> wrote in message
    > news:...
    > : 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
    Kai-Uwe Bux, Feb 26, 2006
    #3
  4. "Kai-Uwe Bux" <> wrote in message
    news:dtscim$rus$...
    : 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/Articles/Cuj/03.ForeachTransform/ForEachTransform.html


    Thank you for the correction,
    Ivan
    --
    http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
    Ivan Vecerina, Feb 26, 2006
    #4
  5. Raider

    Daniel T. Guest

    In article <>,
    "Raider" <> 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.
    Daniel T., Feb 26, 2006
    #5
  6. Raider

    Raider Guest

    > '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
    Raider, Feb 27, 2006
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. optical supercomputing

    Optical Computing: special issue - Natural Computing, Springer

    optical supercomputing, Dec 19, 2008, in forum: C Programming
    Replies:
    0
    Views:
    412
    optical supercomputing
    Dec 19, 2008
  2. optical supercomputing

    Optical Computing: special issue - Natural Computing, Springer

    optical supercomputing, Jan 16, 2009, in forum: C Programming
    Replies:
    0
    Views:
    443
    optical supercomputing
    Jan 16, 2009
  3. Francesco Pietra

    Extract value and average

    Francesco Pietra, Jun 8, 2009, in forum: Python
    Replies:
    4
    Views:
    248
    Glauco
    Jun 9, 2009
  4. Francesco Pietra

    Fwd: Extract value and average

    Francesco Pietra, Jun 9, 2009, in forum: Python
    Replies:
    0
    Views:
    253
    Francesco Pietra
    Jun 9, 2009
  5. Peter Szinek

    Computing average of time deltas

    Peter Szinek, Mar 19, 2007, in forum: Ruby
    Replies:
    1
    Views:
    128
    Phrogz
    Mar 19, 2007
Loading...

Share This Page