By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,231 Members | 1,800 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,231 IT Pros & Developers. It's quick & easy.

Problem with Exponent program

P: n/a
I'm getting a compilation error with this program, something about the
instation of invArg; here's the code:

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

template<class T>
class invArg
{
public:
invArg(T& arg):inv(arg){}
virtual void Write()const{cout << inv << endl;}
private:
T inv;
};

template<class T>
class Exp
{
public:
T operator()(const T& base, T exp)throw(invArg<T>)
{
if(exp<0)
1/operator()(base,exp);
else if(base==0)
throw invArg<T>(base);
else
{
T ret=1;
for(;exp--;)
base*=exp;
return ret;
}
}
};

int main()
{
for(;;)
{
try
{
long double base,exp;
cout << "Enter a base and an exponent: " << endl;
cin >> base >> exp;
cout << base <<"^" << exp << "=" << fixed << Exp<long
double>()(base,exp) << endl;
}
catch(invArg<long double>& inv)
{
inv.Write();
}
system("PAUSE");
return 0;
}
}

I think the type checking is too strong; any suggestions? Thanks!!!

Dec 18 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
Protoman wrote:
I'm getting a compilation error with this program, something about the
instation of invArg; here's the code:
"Something about..." is not a very good description of an error message.
template<class T>
class invArg
{
public:
invArg(T& arg):inv(arg){}
virtual void Write()const{cout << inv << endl;}
private:
T inv;
};


The constructor should take `const T &`. It doesn't now and that is why

throw invArg<T> (base);

fails to compile; `base` is `const T &`.

I would also consider making the constructor `explicit`.

Martin.
Dec 18 '05 #2

P: n/a
Here's the new code; now after I type the numbers, the program closes.
What do I do?

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

template<class T>
class invArg
{
public:
explicit invArg(const T& arg):inv(arg){}
virtual void Write()const{cout << inv << endl;}
private:
T inv;
};

template<class T>
class Exp
{
public:
T operator()(const T& base, T exp)throw(invArg<T>)
{
if(exp<0)
1/operator()(base,exp);
else if(base==0)
throw invArg<T>(base);
else
{
T ret=1;
for(;exp--;)
exp*=base;
return ret;
}
}
};

int main()
{
try
{
long double base,exp;
cout << "Enter a base and an exponent: " << endl;
cin >> base >> exp;
cout << base <<"^" << exp << "=" << fixed << Exp<long
double>()(base,exp) << endl;
system("PAUSE");
return 0;
}
catch(invArg<const long double>& inv)
{
inv.Write();
}
}

Any suggestions? Thanks!!!

Dec 19 '05 #3

P: n/a
Protoman wrote:
Here's the new code; now after I type the numbers, the program closes.
What do I do?
First, please indent your program properly. You make it VERY hard to
follow your logic when everything is on the left margin.

Second, how can we know if you don't tell us what the numbers are that
resulted in the behavior?
#include <iostream>
#include <cstdlib>
using namespace std;

template<class T>
class invArg
{
public:
explicit invArg(const T& arg):inv(arg){}
virtual void Write()const{cout << inv << endl;}
private:
T inv;
};

template<class T>
class Exp
{
public:
T operator()(const T& base, T exp)throw(invArg<T>)
{
if(exp<0)
1/operator()(base,exp);
What on earth is the above supposed to do? Are you missing a return
statement? In any case, if exp is negative, you get an infinite loop
until you overrun your stack. Please explain what you intended with
the above.
else if(base==0)
throw invArg<T>(base);
else
{
T ret=1;
for(;exp--;)
exp*=base;
return ret;
??? You initialize ret to 1, then you never change ret. Therefore, the
above will always return 1. Meanwhile, exp gets bigger and bigger -
how will it ever get to zero?
}
}
};

int main()
{
try
{
long double base,exp;
cout << "Enter a base and an exponent: " << endl;
cin >> base >> exp;
cout << base <<"^" << exp << "=" << fixed << Exp<long
double>()(base,exp) << endl;
system("PAUSE");
return 0;
}
catch(invArg<const long double>& inv)
{
inv.Write();
Probably you should insert another system("PAUSE") here, in case your
program throws (which I assume it did).
}
}


You know, I think it's fairly likely you're just a troll, but I suppose
you are mildly entertaining.

Best regards,

Tom

Dec 19 '05 #4

P: n/a
OK, I'm trying to make it work like exponents in algebra work; i.e.
negative exponents are reciprocals of their positive counterparts,
fractional exponents are roots, like that. And I'm trying to make it
throw if one of these four things: the base is 0, both the base and exp
is 0, or its 0 rasised to zero or a negative. Does that make it
clearer? Thanks!!!

Dec 19 '05 #5

P: n/a

"Protoman" <Pr**********@gmail.com> wrote in message
T operator()(const T& base, T exp)throw(invArg<T>)
{
if(exp<0)
1/operator()(base,exp);
else if(base==0)
throw invArg<T>(base);
else
{
T ret=1;
for(;exp--;)
exp*=base;
return ret;
}
}


Pass a negative number as the exponent to that function. What happens? It
calls operator() again, passing it the SAME values. Which means it passes a
negative value for exp again. So then what happens...?

Also, look at the loop. What's it doing? Look carefully, especially at how
ret gets its value...

-Howard

Dec 19 '05 #6

P: n/a

Howard wrote:
"Protoman" <Pr**********@gmail.com> wrote in message
T operator()(const T& base, T exp)throw(invArg<T>)
{
if(exp<0)
1/operator()(base,exp);
else if(base==0)
throw invArg<T>(base);
else
{
T ret=1;
for(;exp--;)
exp*=base;
return ret;
}
}

Pass a negative number as the exponent to that function. What happens? It
calls operator() again, passing it the SAME values. Which means it passes a
negative value for exp again. So then what happens...?


OK, this should work, but how do I get it to stop closing after I
input?

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

template<class T>
class invArg
{
public:
explicit invArg(const T& arg):inv(arg){}
virtual void Write()const{cout << inv << endl;}
private:
T inv;
};

template<class T>
class Exp
{
public:
T operator()(const T& base, T exp)throw(invArg<T>)
{
if(exp<0)
goto neg;
else if(base==0)
throw invArg<T>(base);
else
{
T ret=1;
for(;exp--;)
ret*=base;
return ret;
}
neg:
{
T ret=1;
for(;exp--;)
ret*=base;
return 1/ret;
}
}
};

int main()
{
try
{
long double base,exp;
cout << "Enter a base and an exponent: " << endl;
cin >> base >> exp;
cout << base <<"^" << exp << "=" << fixed << Exp<long
double>()(base,exp) << endl;
system("PAUSE");
return 0;
}
catch(invArg<const long double>& inv)
{
inv.Write();
}
}

Any suggestions? Thanks!!! Also, look at the loop. What's it doing? Look carefully, especially at how
ret gets its value...

-Howard


Dec 19 '05 #7

P: n/a

Protoman wrote:
OK, this should work, but how do I get it to stop closing after I
input?
Is this a joke?
What do you mean by "work"?

See comments below.

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

template<class T>
class invArg
{
public:
explicit invArg(const T& arg):inv(arg){}
virtual void Write()const{cout << inv << endl;}
It's not very helpful to just print the argument without any message
now, is it?
private:
T inv;
};

template<class T>
class Exp
Why make this a class and not a freestanding function?

You are not using any object orientated features here that would
require this to be a class. Don't do it simply for the sake of saying
"I made a class".
{
public:
T operator()(const T& base, T exp)throw(invArg<T>)
Why is exp not a const reference? It should be.
{
if(exp<0)
goto neg;
GOTO??? There is absolutely no need to use goto to achive the desired
program flow here. When you code, don't think about the exceptions
first, think about the commonalities....
else
{
T ret=1;
for(;exp--;)
A while loop would be way more appropriate here.

But the bigger issue is that this can only work for integer values of
exp. I.e. if exp is a fraction (which it can be based on you declaring
it as long double), this code will endless-loop.
ret*=base;
return ret;
}
neg:
{
T ret=1;
for(;exp--;)
ret*=base;
return 1/ret;
You are performing the same actions here as in the "positive" case, but
only invert the result. This can be done way simpler without using
goto.
}
}
};

int main()
{
try
{
long double base,exp;
cout << "Enter a base and an exponent: " << endl;
cin >> base >> exp;
You are never checking if this succeeded (cin still valid)...
cout << base <<"^" << exp << "=" << fixed << Exp<long
double>()(base,exp) << endl;
system("PAUSE");
This is not portable.
If you really have to do this (I'm sure your teacher would be ok
without it), just to a getline( cin, temp); or so...
return 0;
}
catch(invArg<const long double>& inv)
Wrong....

catch( const invArg<long double>& inv)
{
inv.Write();
}
}


Dec 19 '05 #8

P: n/a

"Protoman" <Pr**********@gmail.com> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.com...

Howard wrote:
"Protoman" <Pr**********@gmail.com> wrote in message
> T operator()(const T& base, T exp)throw(invArg<T>)
> {
> if(exp<0)
> 1/operator()(base,exp);
> else if(base==0)
> throw invArg<T>(base);
> else
> {
> T ret=1;
> for(;exp--;)
> exp*=base;
> return ret;
> }
> }
>


Pass a negative number as the exponent to that function. What happens?
It
calls operator() again, passing it the SAME values. Which means it
passes a
negative value for exp again. So then what happens...?


OK, this should work, but how do I get it to stop closing after I
input?

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

template<class T>
class invArg
{
public:
explicit invArg(const T& arg):inv(arg){}
virtual void Write()const{cout << inv << endl;}
private:
T inv;
};

template<class T>
class Exp
{
public:
T operator()(const T& base, T exp)throw(invArg<T>)
{
if(exp<0)
goto neg;
else if(base==0)
throw invArg<T>(base);
else
{
T ret=1;
for(;exp--;)
ret*=base;
return ret;
}
neg:
{
T ret=1;
for(;exp--;)
ret*=base;
return 1/ret;
}
}
};

int main()
{
try
{
long double base,exp;
cout << "Enter a base and an exponent: " << endl;
cin >> base >> exp;
cout << base <<"^" << exp << "=" << fixed << Exp<long
double>()(base,exp) << endl;
system("PAUSE");
return 0;
}
catch(invArg<const long double>& inv)
{
inv.Write();
}
}

Any suggestions? Thanks!!!


Yes, I have suggestions:

1) Read the other posts. One of the responders tells you why your app is
closing.
2) Use your debugger. It will tell you two things: first, that your
solution above does not work properly, and second, what it's doing when it
closes.
3) Why have you used a goto call? That's rarely a good design choice. Why
not just a block of code right where you need it? Or better yet, why not do
it the way you were (sort of), but pass the correct values when exp is
negative?
4) Do something about the editor or newsreader you're using: without
indentation, this is very hard to read.
5) What data types is this supposed to operate on? Consider especially what
it means to call the operator with a negative exponent when your type is
integral. If you only need to handle double (and/or float) do you really
need a template for this class? Seems like just handling the double type
with a function would work, without templates at all.
6) There's already a function called pow which handles raising to a power,
so why rewrite it?

-Howard

Dec 20 '05 #9

P: n/a

in*****@gmail.com wrote:
If you really have to do this (I'm sure your teacher would be ok
without it), just to a getline( cin, temp); or so...


This is not homework, it's a hobby. And does pow handle negative
exponents?

Dec 20 '05 #10

P: n/a

Protoman wrote:
in*****@gmail.com wrote:
If you really have to do this (I'm sure your teacher would be ok
without it), just to a getline( cin, temp); or so...


This is not homework, it's a hobby. And does pow handle negative
exponents?


If it's a hobby I seriously suggest a good C++ book like "Accelerated
C++". And a few good books on general programming.

Yes, pow() handles negative exponents as well as fractions as exponent.

Cheers,
Andre

Dec 20 '05 #11

P: n/a
Good. I'll use that. No sense in reinventing the square wheel.

Dec 20 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.