Is this program right?

Discussion in 'C++' started by Protoman, Sep 11, 2005.

  1. Protoman

    Protoman Guest

    Hey, is this program right? It calculates the average, harmonic mean,
    quadratic mean, and the standard deviation for two numbers. Can you
    proofread it for me?
    Here it is:

    #include <iostream>
    #include <cstdlib>
    #include <cmath>
    using namespace std;

    template <class T>
    class avg
    {
    public:
    T operator()(const T& num, const T& num2)const
    {
    T ret=((num+num2)/2);
    return ret;
    }
    T operator()(const T& num, const T& num2, int x)const
    {
    T ret=(sqrt(pow(num,2)+pow(num,2)));
    return ret;
    }
    T operator()(const T& num, const T& num2,int x,int y)const
    {
    T ret=(2/(1/num+1/num2));
    return ret;
    }
    operator T()const{return static_cast<T>(value);}
    private:
    T value;
    };

    template <class T>
    class Stat
    {
    public:
    T operator()(T avg,const T& num,const T& num2)const
    {
    T ret=num-avg;
    T ret2=num2-avg;
    T ret3=(pow(ret,2)+pow(ret2,2)/2);
    T ret4=sqrt(ret3);
    return ret4;
    }
    operator T()const{return static_cast<T>(value);}
    private:
    T value;
    };

    int main()
    {
    for(;;)
    {
    long double num;
    long double num2;
    avg<long double> Avg;
    Stat<long double> StdDev;
    cout << "Enter two numbers: " << endl;
    cin >> num >> num2;
    cout << "Here's the average: " << fixed << Avg(num,num2) << endl;
    cout << "Here's the quadratic mean: " << fixed << Avg(num,num2,0) <<
    endl;
    cout << "Here's the harmonic mean: " << fixed << Avg(num,num2,0,0) <<
    endl;
    cout << "Here's the standard deviation: " << fixed <<
    StdDev(Avg(num,num2),num,num2)
    << endl;
    }
    system ("PAUSE");
    return 0;
    }

    Also, is there anyway I can make it so StdDev can use Avg's arguments
    so I don't need StdDev to have copies of Avg's arguments? And is there
    anyway I can make Avg and StdDev have variable numbers of paramaters; I
    don't want to recompile everytime I want to do more (or less) numbers?
    Thanks a lot.
     
    Protoman, Sep 11, 2005
    #1
    1. Advertising

  2. Protoman wrote:
    > Hey, is this program right? It calculates the average, harmonic mean,
    > quadratic mean, and the standard deviation for two numbers. Can you
    > proofread it for me?
    > Here it is:
    >
    > #include <iostream>
    > #include <cstdlib>
    > #include <cmath>
    > using namespace std;
    >
    > template <class T>
    > class avg
    > {
    > public:
    > T operator()(const T& num, const T& num2)const
    > {
    > T ret=((num+num2)/2);
    > return ret;
    > }
    > T operator()(const T& num, const T& num2, int x)const
    > {
    > T ret=(sqrt(pow(num,2)+pow(num,2)));
    > return ret;
    > }
    > T operator()(const T& num, const T& num2,int x,int y)const
    > {
    > T ret=(2/(1/num+1/num2));
    > return ret;
    > }
    > operator T()const{return static_cast<T>(value);}
    > private:
    > T value;
    > };
    >
    > template <class T>
    > class Stat
    > {
    > public:
    > T operator()(T avg,const T& num,const T& num2)const
    > {
    > T ret=num-avg;
    > T ret2=num2-avg;
    > T ret3=(pow(ret,2)+pow(ret2,2)/2);
    > T ret4=sqrt(ret3);
    > return ret4;
    > }
    > operator T()const{return static_cast<T>(value);}
    > private:
    > T value;
    > };
    >
    > int main()
    > {
    > for(;;)
    > {
    > long double num;
    > long double num2;
    > avg<long double> Avg;
    > Stat<long double> StdDev;
    > cout << "Enter two numbers: " << endl;
    > cin >> num >> num2;
    > cout << "Here's the average: " << fixed << Avg(num,num2) << endl;
    > cout << "Here's the quadratic mean: " << fixed << Avg(num,num2,0) <<
    > endl;
    > cout << "Here's the harmonic mean: " << fixed << Avg(num,num2,0,0) <<
    > endl;
    > cout << "Here's the standard deviation: " << fixed <<
    > StdDev(Avg(num,num2),num,num2)
    > << endl;
    > }
    > system ("PAUSE");
    > return 0;
    > }


    If you say it works I'm prepared to believe it, but it is seriously
    misusing C++. What you need for the task is not template classes but
    template functions. For instaance

    template <class T>
    T mean(const T& num, const T& num2)
    {
    T ret=((num+num2)/2);
    return ret;
    }

    template <class T>
    T quadratic_mean(const T& num, const T& num2)
    {
    T ret=(sqrt(pow(num,2)+pow(num,2)));
    return ret;
    }

    With template functions the rest of your code becomes simpler and more
    natural.

    long double num;
    long double num2;
    cout << "Enter two numbers: " << endl;
    cin >> num >> num2;
    cout << "Here's the average: " << fixed << mean(num,num2) << endl;
    cout << "Here's the quadratic mean: " << fixed <<
    quadratic_mean(num,num2) <<

    Because you aren't using classes you don't have to declare the silly avg
    and StdDev variables that you did in your original code. Not do you have
    to add the spurious extra int parameters to your overloaded operators.

    > Also, is there anyway I can make it so StdDev can use Avg's arguments
    > so I don't need StdDev to have copies of Avg's arguments?


    I don't think so, and it's not clear to me why you would want to do this.

    > And is there
    > anyway I can make Avg and StdDev have variable numbers of paramaters; I
    > don't want to recompile everytime I want to do more (or less) numbers?


    Yes, use a vector or an array.

    > Thanks a lot.
    >


    john
     
    John Harrison, Sep 11, 2005
    #2
    1. Advertising

  3. Protoman

    mlimber Guest

    Protoman wrote:
    > Hey, is this program right? It calculates the average, harmonic mean,
    > quadratic mean, and the standard deviation for two numbers. Can you
    > proofread it for me?
    > Here it is:
    >
    > #include <iostream>
    > #include <cstdlib>
    > #include <cmath>
    > using namespace std;
    >
    > template <class T>
    > class avg
    > {
    > public:
    > T operator()(const T& num, const T& num2)const
    > {
    > T ret=((num+num2)/2);
    > return ret;
    > }
    > T operator()(const T& num, const T& num2, int x)const
    > {
    > T ret=(sqrt(pow(num,2)+pow(num,2)));
    > return ret;
    > }
    > T operator()(const T& num, const T& num2,int x,int y)const
    > {
    > T ret=(2/(1/num+1/num2));
    > return ret;
    > }
    > operator T()const{return static_cast<T>(value);}
    > private:
    > T value;
    > };


    This is confusing. Why make it a class at all? Use template functions
    instead. Allowing the programmer to override operator() may be a cool
    feature, but you're abusing here, as can be discerned from the dummy
    parameters needed to distinguish the different mean calculations. It is
    far clearer to name the functions appropriately (e.g. Mean,
    HarmonicMean, etc.). The last operator doesn't need a static_cast,
    since value is T. Also, value can never be initialized since it is
    private, so that operator always returns garbage.

    > template <class T>
    > class Stat
    > {
    > public:
    > T operator()(T avg,const T& num,const T& num2)const
    > {
    > T ret=num-avg;
    > T ret2=num2-avg;
    > T ret3=(pow(ret,2)+pow(ret2,2)/2);


    This formula seems fishy.

    > T ret4=sqrt(ret3);
    > return ret4;
    > }
    > operator T()const{return static_cast<T>(value);}
    > private:
    > T value;
    > };


    The same principle applies here. Don't make it a class and don't use
    operator().

    >
    > int main()
    > {
    > for(;;)
    > {
    > long double num;
    > long double num2;
    > avg<long double> Avg;
    > Stat<long double> StdDev;
    > cout << "Enter two numbers: " << endl;
    > cin >> num >> num2;
    > cout << "Here's the average: " << fixed << Avg(num,num2) << endl;
    > cout << "Here's the quadratic mean: " << fixed << Avg(num,num2,0) <<
    > endl;
    > cout << "Here's the harmonic mean: " << fixed << Avg(num,num2,0,0) <<
    > endl;
    > cout << "Here's the standard deviation: " << fixed <<
    > StdDev(Avg(num,num2),num,num2)
    > << endl;
    > }
    > system ("PAUSE");
    > return 0;
    > }
    >
    > Also, is there anyway I can make it so StdDev can use Avg's arguments
    > so I don't need StdDev to have copies of Avg's arguments? And is there
    > anyway I can make Avg and StdDev have variable numbers of paramaters; I
    > don't want to recompile everytime I want to do more (or less) numbers?
    > Thanks a lot.


    You can use TypeLists from _Modern C++ Design_ and the Loki library
    (http://sf.net/projects/loki-lib) to get a variable number of template
    parameters. Boost may have something similar. In any case, you
    shouldn't need them if you alter the program as I suggested above.

    Cheers! --M
     
    mlimber, Sep 11, 2005
    #3
  4. Protoman

    Protoman Guest

    I'm wondering if you, mlimber, ever took statistics; that formula "that
    seems fishy" is the variance and standard deviation formula combined
    into one. And I've done my class conversion ops that way for years and
    they worked just fine.
     
    Protoman, Sep 11, 2005
    #4
  5. Protoman

    Protoman Guest

    And, John, here's my program updated to your advice:

    #include <iostream>
    #include <cstdlib>
    #include <cmath>
    using namespace std;

    template <class T>
    T mean(T& num,T& num2,T& num3,T& num4,T& num5)
    {
    const static T ret=((num+num2+num3+num4+num5)/5);
    return ret;
    }

    template <class T>
    T harmonic_mean(T& num,T& num2,T& num3,T& num4,T& num5)
    {
    const static T ret=(5/(1/num+1/num2+1/num3+1/num4+1/num5));
    return ret;
    }

    template <class T>
    T quadratic_mean(T& num,T& num2,T& num3,T& num4,T& num5)
    {
    const static T
    ret=(sqrt(pow(num,2)+pow(num2,2)+pow(num3,2)+pow(num4,2)+pow(num5,2))/5);
    return ret;
    }

    template <class T>
    T std_dev(T avg,T& num,T& num2,T& num3,T& num4,T& num5)
    {
    const static T ret=num-avg;
    const static T ret2=num2-avg;
    const static T ret3=num3-avg;
    const static T ret4=num4-avg;
    const static T ret5=num5-avg;
    const static T
    ret6=((pow(ret,2)+pow(ret2,2)+pow(ret3,2)+pow(ret4,2)+pow(ret5,2))/5);
    const static T ret7=sqrt(ret6);
    return ret7;
    }

    int main()
    {
    for(;;)
    {
    long double num;
    long double num2;
    long double num3;
    long double num4;
    long double num5;
    cout << "Enter five numbers: " << endl;
    cin >> num >> num2 >> num3 >> num4 >> num5;
    cout << "Here's the average: " << fixed << mean<long
    double>(num,num2,num3,num4,num5) << endl;
    cout << "Here's the quadratic mean: " << fixed << harmonic_mean<long
    double>(num,num2,num3,num4,num5) << endl;
    cout << "Here's the harmonic mean: " << fixed << quadratic_mean<long
    double>(num,num2,num3,num4,num5) << endl;
    cout << "Here's the standard deviation: " << fixed << std_dev<long
    double>(mean<long double>(num,num2,num3,num4,num5)
    ,num,num2,num3,num4,num5) << endl;
    }
    system ("PAUSE");
    return 0;
    }

    Is there anyway I can make it clearer und more precise und concise, not
    to mention more efficient?
     
    Protoman, Sep 11, 2005
    #5
  6. Protoman

    mlimber Guest

    Protoman wrote:
    > I'm wondering if you, mlimber, ever took statistics; that formula "that
    > seems fishy" is the variance and standard deviation formula combined
    > into one. And I've done my class conversion ops that way for years and
    > they worked just fine.


    If you say the formula's right, I'll trust you. I didn't bother to look
    it up. Besides, names like "Stat" and "ret", "ret2", and "ret3" (none
    of which are actually returned) don't exactly communicate your intent,
    so I trust that you'll excuse me for missing it on a cursory reading.

    In any case, I wasn't saying that your conversion operators wouldn't
    compile; I was saying the static_cast is utterly unnecessary, adds no
    readability, and only begs for confusion from others reading your code.
    The fact that you've written code this way for years is no excuse to
    continue writing it that way. The conversion operator itself is also
    utterly unnecessary as written, and in fact, it's an error because
    "value" is not initialized in either class and cannot be. Any user
    calling it will get bogus data, but it could be a hard error to detect
    since the compiler might invoke that operator for an implicit
    conversion task somewhere. (Yikes!)

    Your original code may generate the desired results, but it is what the
    FAQ for this group would call thoroughly immoral.

    Cheers! --M
     
    mlimber, Sep 11, 2005
    #6
  7. Protoman

    mlimber Guest

    Protoman wrote:
    > And, John, here's my program updated to your advice:
    >
    > #include <iostream>
    > #include <cstdlib>
    > #include <cmath>
    > using namespace std;
    >
    > template <class T>
    > T mean(T& num,T& num2,T& num3,T& num4,T& num5)
    > {
    > const static T ret=((num+num2+num3+num4+num5)/5);


    Not static! This function will always return the value of the first
    invocation no matter how many times you call it.

    > return ret;
    > }


    Following John's advice of using vector:

    #include <vector>

    template <typename T>
    T Mean( const vector<T>& data )
    {
    T sum = 0;
    for( vector<T>::const_iterator i=data.begin(); i != data.end(); ++i )
    {
    sum += *i;
    }
    return sum / data.size();
    }

    [snip]
    > Is there anyway I can make it clearer und more precise und concise, not
    > to mention more efficient?


    Don't hardcode the number of parameters unless that's the only number
    you'll ever need.

    Cheers! --M
     
    mlimber, Sep 11, 2005
    #7
  8. Protoman

    mlimber Guest

    mlimber wrote:
    > Protoman wrote:
    > > Is there anyway I can make it clearer und more precise und concise, not
    > > to mention more efficient?

    >
    > Don't hardcode the number of parameters unless that's the only number
    > you'll ever need.


    Oh, and you could also use the standard library functions if you're
    working with standard containers like vector. Check out std::accumulate
    in <algorithm>, for instance.

    Cheers! --M
     
    mlimber, Sep 11, 2005
    #8
  9. Protoman

    Protoman Guest

    Can you generalize that vector algorithm for me?
     
    Protoman, Sep 11, 2005
    #9
  10. Protoman

    mlimber Guest

    Protoman wrote:
    > Can you generalize that vector algorithm for me?


    Not sure what you're asking for. I wrote Mean as a template function
    using a vector. It doesn't get much more generic than that. The other
    functions would be similar -- iterate through each element and do some
    calculation on them.

    The main function might look something like:

    int main()
    {
    vector<float>::size_type size;
    cout << "Enter the number of points: " << flush;
    cin >> size;
    vector<float> data( size );
    for( vector<float>::iterator i=data.begin(); i != data.end(); ++i )
    {
    cin >> *i;
    }
    cout << "Mean: " << Mean( data ) << endl;
    // ...
    return 0;
    }

    You could always use istream_iterators and back_inserters from the STL
    to make this code more compact, but that may not be suitable for a real
    application if you needed to do error checking or something.

    Cheers! --M
     
    mlimber, Sep 11, 2005
    #10
  11. Protoman

    Greg Guest

    Protoman wrote:
    > And, John, here's my program updated to your advice:
    >
    > #include <iostream>
    > #include <cstdlib>
    > #include <cmath>
    > using namespace std;
    >
    > ...
    > template <class T>
    > T harmonic_mean(T& num,T& num2,T& num3,T& num4,T& num5)
    > {
    > const static T ret=(5/(1/num+1/num2+1/num3+1/num4+1/num5));
    > return ret;
    > }
    >
    > int main()
    > {
    > for(;;)
    > {
    > long double num;
    > long double num2;
    > long double num3;
    > long double num4;
    > long double num5;
    > cout << "Enter five numbers: " << endl;
    > cin >> num >> num2 >> num3 >> num4 >> num5;
    > cout << "Here's the average: " << fixed << mean<long
    > double>(num,num2,num3,num4,num5) << endl;
    > cout << "Here's the quadratic mean: " << fixed << harmonic_mean<long
    > double>(num,num2,num3,num4,num5) << endl;
    > cout << "Here's the harmonic mean: " << fixed << quadratic_mean<long
    > double>(num,num2,num3,num4,num5) << endl;
    > cout << "Here's the standard deviation: " << fixed << std_dev<long
    > double>(mean<long double>(num,num2,num3,num4,num5)
    > ,num,num2,num3,num4,num5) << endl;
    > }
    > system ("PAUSE");
    > return 0;
    > }
    >
    > Is there anyway I can make it clearer und more precise und concise, not
    > to mention more efficient?


    The program should validate its inputs. For example, if the user enters
    a 0 as one of the numbers that the program asks for, what is likely to
    happen when the program calculates their harmonic mean?

    Also, I don't see any benefit from using template functions. On the
    contrary, by having to instantiate these routines for a float, when the
    program already has instantiated them for a double, provides no added
    benefit and simply bloats the code. A set of non-template functions
    accepting doubles would seem to make a lot more sense.

    Greg
     
    Greg, Sep 11, 2005
    #11
  12. Protoman

    Protoman Guest

    When I say "generalize", I mean, for all the different types of means;
    I'm not very good at STL.
     
    Protoman, Sep 11, 2005
    #12
  13. Protoman

    Protoman Guest

    OK, I tried it, but it doesn't compile; here are the errors:

    C:\Dev-Cpp\average3.cpp In function `T Mean(const std::vector<T,
    std::allocator<_CharT> >&)': expected `;' before "i"
    11 C:\Dev-Cpp\average3.cpp `i' undeclared (first use this function)
    C:\Dev-Cpp\average3.cpp In function `T Mean(const std::vector<T,
    std::allocator<_CharT> >&) [with T = float]': instantiated from here
    11 C:\Dev-Cpp\average3.cpp dependent-name `
    std::vector<T,std::allocator<_CharT> >::const_iterator' is parsed as a
    non-type, but instantiation yields a type
    11 C:\Dev-Cpp\average3.cpp say `typename
    std::vector<T,std::allocator<_CharT> >::const_iterator' if a type is
    meant

    I wonder what's wrong? Hope this helps!
     
    Protoman, Sep 11, 2005
    #13
  14. Protoman

    Cy Edmunds Guest

    "Protoman" <> wrote in message
    news:...
    > Hey, is this program right? It calculates the average, harmonic mean,
    > quadratic mean, and the standard deviation for two numbers. Can you
    > proofread it for me?
    > Here it is:
    >
    > #include <iostream>
    > #include <cstdlib>
    > #include <cmath>
    > using namespace std;
    >
    > template <class T>
    > class avg
    > {
    > public:
    > T operator()(const T& num, const T& num2)const
    > {
    > T ret=((num+num2)/2);
    > return ret;
    > }
    > T operator()(const T& num, const T& num2, int x)const
    > {
    > T ret=(sqrt(pow(num,2)+pow(num,2)));
    > return ret;
    > }
    > T operator()(const T& num, const T& num2,int x,int y)const
    > {
    > T ret=(2/(1/num+1/num2));
    > return ret;
    > }
    > operator T()const{return static_cast<T>(value);}
    > private:
    > T value;
    > };
    >
    > template <class T>
    > class Stat
    > {
    > public:
    > T operator()(T avg,const T& num,const T& num2)const
    > {
    > T ret=num-avg;
    > T ret2=num2-avg;
    > T ret3=(pow(ret,2)+pow(ret2,2)/2);
    > T ret4=sqrt(ret3);
    > return ret4;
    > }
    > operator T()const{return static_cast<T>(value);}
    > private:
    > T value;
    > };
    >
    > int main()
    > {
    > for(;;)
    > {
    > long double num;
    > long double num2;
    > avg<long double> Avg;
    > Stat<long double> StdDev;
    > cout << "Enter two numbers: " << endl;
    > cin >> num >> num2;
    > cout << "Here's the average: " << fixed << Avg(num,num2) << endl;
    > cout << "Here's the quadratic mean: " << fixed << Avg(num,num2,0) <<
    > endl;
    > cout << "Here's the harmonic mean: " << fixed << Avg(num,num2,0,0) <<
    > endl;
    > cout << "Here's the standard deviation: " << fixed <<
    > StdDev(Avg(num,num2),num,num2)
    > << endl;
    > }
    > system ("PAUSE");
    > return 0;
    > }
    >
    > Also, is there anyway I can make it so StdDev can use Avg's arguments
    > so I don't need StdDev to have copies of Avg's arguments? And is there
    > anyway I can make Avg and StdDev have variable numbers of paramaters; I
    > don't want to recompile everytime I want to do more (or less) numbers?
    > Thanks a lot.
    >


    You can use classes to make your statistic work with any number of samples.
    For instance (unchecked):

    class sample_mean
    {
    private:
    unsigned m_count; // number of samples
    double m_sum_x1; // sum of samples
    public:
    sample_mean() : m_count(0), m_sum_x1(0.0) {}
    unsigned n() const {return m_count;}
    double xbar() const // no check for 0 samples
    {
    return m_sum_x1 / m_count;
    }
    template <typename T>
    sample_mean &operator () (T x)
    {
    ++m_count;
    m_sum_x1 += static_cast<double>(x);
    return *this;
    }
    void clear()
    {
    m_count = 0;
    m_sum_x1 = 0.0;
    }
    };

    You use it like this:

    sample_mean m;
    m(1.2)(3.6)(-0.4);
    std::cout << m.xbar() << '\n';

    --
    Cycho{HHR}
    http://home.rochester.rr.com/cyhome/
     
    Cy Edmunds, Sep 11, 2005
    #14
  15. Protoman

    Protoman Guest

    I want to do it w/ functions and STL.
     
    Protoman, Sep 11, 2005
    #15
  16. Protoman

    Protoman Guest

    I'm always getting an error on the function's for loop; keeps saying i
    is undeclared.
     
    Protoman, Sep 12, 2005
    #16
  17. Protoman

    mlimber Guest

    Protoman wrote:
    > I want to do it w/ functions and STL.


    I'd suggest getting a good book on STL, then. Stroustrup's _C++PL_
    gives an overview of the STL, and _The C++ Standard Library : A
    Tutorial and Reference_ by Nicolai M. Josuttis goes into greater depth.

    Cheers! --M
     
    mlimber, Sep 12, 2005
    #17
  18. Protoman

    Protoman Guest

    Where can I buy that; at Borders?
     
    Protoman, Sep 12, 2005
    #18
  19. "mlimber" wrote:
    >I'd suggest getting a good book on STL, then. Stroustrup's _C++PL_
    >gives an overview of the STL, and _The C++ Standard Library : A
    >Tutorial and Reference_ by Nicolai M. Josuttis goes into greater depth.


    And then "Protoman" wrote:
    >Where can I buy that; at Borders?


    Somebody who claims to be "a bloody Cal State professor!!!!" (sic) and
    "the asst. head of systems programming in the R&D Dept." (sic) where
    "We're calculating thruster angles for a prototype ion drive engine."
    needs to ask where to buy a well known book from a well known
    publisher? The plot thickens ...

    Roberto Waltman

    [ Please reply to the group, ]
    [ return address is invalid. ]
     
    Roberto Waltman, Sep 12, 2005
    #19
  20. Protoman

    Protoman Guest

    Why are you doing this to me?!!!!!!!!!!!? I'm just asking if you know
    if Borders *stocks* that book?!!!!? Let's go back to the original
    topic. Please, I beseech you!!!!
     
    Protoman, Sep 12, 2005
    #20
    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. Tom
    Replies:
    0
    Views:
    434
  2. =?Utf-8?B?QmlzaG95?=
    Replies:
    0
    Views:
    1,003
    =?Utf-8?B?QmlzaG95?=
    Dec 28, 2006
  3. Bogdan
    Replies:
    1
    Views:
    817
    Bogdan
    Jun 16, 2009
  4. Leon
    Replies:
    3
    Views:
    182
    TaeHo Yoo
    Nov 26, 2004
  5. Oran
    Replies:
    2
    Views:
    560
Loading...

Share This Page