Problem with Exponent program


P

Protoman

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

Advertisements

M

Martin Vejnar

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

Protoman

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

Thomas Tutone

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

Protoman

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

Howard

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

Advertisements

P

Protoman

Howard said:
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!!!
 
I

int2str

Protoman said:
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....
 
H

Howard

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

Protoman

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

int2str

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

Advertisements


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

Top