Velocity Reviews > C++ > Is this program right?

# Is this program right?

Protoman
Guest
Posts: n/a

 09-11-2005
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.

John Harrison
Guest
Posts: n/a

 09-11-2005
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

mlimber
Guest
Posts: n/a

 09-11-2005
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

Protoman
Guest
Posts: n/a

 09-11-2005
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
Guest
Posts: n/a

 09-11-2005

#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(n um4,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?

mlimber
Guest
Posts: n/a

 09-11-2005
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
Guest
Posts: n/a

 09-11-2005
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
Guest
Posts: n/a

 09-11-2005

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

Protoman
Guest
Posts: n/a

 09-11-2005
Can you generalize that vector algorithm for me?

mlimber
Guest
Posts: n/a

 09-11-2005
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