Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is this program right?

219 views
Skip to first unread message

Protoman

unread,
Sep 10, 2005, 8:02:39 PM9/10/05
to
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.

John Harrison

unread,
Sep 10, 2005, 8:16:20 PM9/10/05
to

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

mlimber

unread,
Sep 10, 2005, 8:29:02 PM9/10/05
to
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

Protoman

unread,
Sep 10, 2005, 8:38:19 PM9/10/05
to
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

unread,
Sep 10, 2005, 9:05:44 PM9/10/05
to
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?

mlimber

unread,
Sep 10, 2005, 9:25:21 PM9/10/05
to

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

unread,
Sep 10, 2005, 9:35:25 PM9/10/05
to
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

unread,
Sep 10, 2005, 9:39:08 PM9/10/05
to

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

unread,
Sep 11, 2005, 12:07:21 AM9/11/05
to
Can you generalize that vector algorithm for me?

mlimber

unread,
Sep 11, 2005, 9:29:38 AM9/11/05
to
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

Greg

unread,
Sep 11, 2005, 9:36:56 AM9/11/05
to
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

Protoman

unread,
Sep 11, 2005, 12:25:38 PM9/11/05
to
When I say "generalize", I mean, for all the different types of means;
I'm not very good at STL.

Protoman

unread,
Sep 11, 2005, 12:43:24 PM9/11/05
to
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!

Cy Edmunds

unread,
Sep 11, 2005, 1:48:57 PM9/11/05
to
"Protoman" <Protom...@gmail.com> wrote in message
news:1126396959.6...@g43g2000cwa.googlegroups.com...

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/


Protoman

unread,
Sep 11, 2005, 2:08:16 PM9/11/05
to
I want to do it w/ functions and STL.

Protoman

unread,
Sep 12, 2005, 1:00:37 AM9/12/05
to
I'm always getting an error on the function's for loop; keeps saying i
is undeclared.

mlimber

unread,
Sep 12, 2005, 8:53:34 AM9/12/05
to
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

Protoman

unread,
Sep 12, 2005, 3:57:19 PM9/12/05
to
Where can I buy that; at Borders?

Roberto Waltman

unread,
Sep 12, 2005, 4:53:15 PM9/12/05
to
"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. ]

Protoman

unread,
Sep 12, 2005, 6:53:55 PM9/12/05
to
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!!!!

Victor Bazarov

unread,
Sep 12, 2005, 8:26:21 PM9/12/05
to
Protoman wrote:
> Why are you doing this to me?!!!!!!!!!!!? I'm just asking if you know
> if Borders *stocks* that book?!!!!?

Are you kidding? What is this, a kindergarten? Have you heard of
"The Web"? If so, visit www.bordersstores.com and search their
inventory. If you haven't, call (888) 81-BOOKS (-26657) and ask
them. Why do you want _us_ to do it for you? And yes, in most
cases when it comes to well-known programming books, Borders does
stock them, although of course I would be guessing without doing
the actual search or talking to them...


Protoman

unread,
Sep 13, 2005, 6:53:09 PM9/13/05
to
OK, here's what I got:

#include <iostream>
#include <cstdlib>
#include <vector>
#include <numeric>
using namespace std;

const long double& mean(void)
{
vector<int> v;
for(int i= 1; i <= 10; ++i)
{
v.push_back(i);
}
const long double ret=accumulate(v.begin(), v.end(), 0.0) / v.size();
return ret;
}
int main()
{
cout << "Mean: " << mean() << endl;
system("PAUSE");
return 0;
}

OK now how do I let it accept user input and let the user determine the
number of parameters?

Victor Bazarov

unread,
Sep 13, 2005, 8:11:57 PM9/13/05
to
Protoman wrote:
> OK, here's what I got:
>
> #include <iostream>
> #include <cstdlib>
> #include <vector>
> #include <numeric>
> using namespace std;
>
> const long double& mean(void)
> {
> vector<int> v;
> for(int i= 1; i <= 10; ++i)
> {
> v.push_back(i);
> }
> const long double ret=accumulate(v.begin(), v.end(), 0.0) / v.size();
> return ret;

This is a cause for undefined behaviour. You're returning a reference
to a local variable. Why don't you simply return by _value_?

> }
> int main()
> {
> cout << "Mean: " << mean() << endl;
> system("PAUSE");
> return 0;
> }
>
> OK now how do I let it accept user input and let the user determine
> the number of parameters?

What does your favourite C++ book say? You've successfully used 'cout',
now it's time to try using 'cin'. All possible examples are in any book
that even remotely considered decent.

V


Protoman

unread,
Sep 13, 2005, 8:31:28 PM9/13/05
to
But how do I store the input in a vector and iterate through it?

hacker++

unread,
Sep 13, 2005, 11:03:52 PM9/13/05
to
Protoman wrote:
> But how do I store the input in a vector and iterate through it?

Did you ever read a C++ book and try doing the above yourself?
Surely there must be a C++ book at the NASA library.....

Kai-Uwe Bux

unread,
Sep 13, 2005, 11:13:06 PM9/13/05
to
Protoman wrote:

> But how do I store the input in a vector and iterate through it?

A classical idiom would be:


int dummy;
while ( std::cin >> dummy ) {
vector_variable.push_back( dummy );
}

Now, you have a vector and can operate on that.

0 new messages