Is this program right?

P

Protoman

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

John Harrison

Protoman said:
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
 
M

mlimber

Protoman said:
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
 
P

Protoman

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

Protoman

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

mlimber

Protoman said:
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
 
M

mlimber

Protoman said:
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
 
M

mlimber

mlimber said:
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
 
M

mlimber

Protoman said:
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
 
G

Greg

Protoman said:
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
 
P

Protoman

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

Protoman

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

Cy Edmunds

Protoman said:
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';
 
M

mlimber

Protoman said:
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
 
R

Roberto Waltman

mlimber said:
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.
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. ]
 
P

Protoman

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

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top