# Is this program right?

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

1. ### ProtomanGuest

Hey, is this program right? It calculates the average, harmonic mean,
quadratic mean, and the standard deviation for two numbers. Can you
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

2. ### John HarrisonGuest

Protoman wrote:
> Hey, is this program right? It calculates the average, harmonic mean,
> quadratic mean, and the standard deviation for two numbers. Can you
> 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 <<

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

> 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

3. ### mlimberGuest

Protoman wrote:
> Hey, is this program right? It calculates the average, harmonic mean,
> quadratic mean, and the standard deviation for two numbers. Can you
> 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
4. ### ProtomanGuest

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
5. ### ProtomanGuest

#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
6. ### mlimberGuest

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
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

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
7. ### mlimberGuest

Protoman wrote:
>
> #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
8. ### mlimberGuest

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
9. ### ProtomanGuest

Can you generalize that vector algorithm for me?

Protoman, Sep 11, 2005
10. ### mlimberGuest

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
11. ### GregGuest

Protoman wrote:
>
> #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
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
12. ### ProtomanGuest

When I say "generalize", I mean, for all the different types of means;
I'm not very good at STL.

Protoman, Sep 11, 2005
13. ### ProtomanGuest

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
14. ### Cy EdmundsGuest

"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
> 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
15. ### ProtomanGuest

I want to do it w/ functions and STL.

Protoman, Sep 11, 2005
16. ### ProtomanGuest

I'm always getting an error on the function's for loop; keeps saying i
is undeclared.

Protoman, Sep 12, 2005
17. ### mlimberGuest

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
18. ### ProtomanGuest

Where can I buy that; at Borders?

Protoman, Sep 12, 2005
19. ### Roberto WaltmanGuest

"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

[ return address is invalid. ]

Roberto Waltman, Sep 12, 2005
20. ### ProtomanGuest

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