Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > The input operator for Rational numbers

Reply
Thread Tools

The input operator for Rational numbers

 
 
Saeed Amrollahi
Guest
Posts: n/a
 
      11-15-2009
Hi

I am going to design and implement a typical library for rational
numbers, something like
Boost.Rational. My class is actually implemented as a template, in a
similar manner to the standard complex class.
I want to handle Whole numbers like rational numbers; As you know,
from point of math view
whole numbers are subset of rational numbers, for example 3 is 3/1.
I like to read both kind of numbers (whole and fraction) in a single
operator>> function. I mean
I want to handle
a
a/b
together. I finally ended with an assumption: Immediately, after
numerator, I should get '/':
template<class T>
std::istream& operator>>(std::istream& is, rational<T>& r)
{
/*
handle the following foramts:
n/d
n
*/
T n, d;
char c = 0; // for '/'
is >> n;
if (is.good()) {
is.get(c);
}
if (c == '/') { // fraction
if (is.good())
is >> d;
}
else if (std::isspace(c) || is.rdstate() & std::ios_base::eofbit)
{ // whole number
d = 1;
}
else {
is.clear(std::ios_base::badbit); // set state
}

if (is) // everything is good
r = rational<T>(n, d);

return is;
}

I know, my code may be inefficient.
Any suggestion for better/more elegant handling different formats and
better efficiency?

Thanks in advance,
-- Saeed Amrollahi

 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      11-16-2009
On Nov 15, 4:07 pm, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:
> I am going to design and implement a typical library for
> rational numbers, something like Boost.Rational. My class is
> actually implemented as a template, in a similar manner to the
> standard complex class. I want to handle Whole numbers like
> rational numbers; As you know, from point of math view whole
> numbers are subset of rational numbers, for example 3 is 3/1.
> I like to read both kind of numbers (whole and fraction) in a
> single operator>> function. I mean I want to handle
> a
> a/b
> together. I finally ended with an assumption: Immediately,
> after numerator, I should get '/':


> template<class T>
> std::istream& operator>>(std::istream& is, rational<T>& r)
> {
> /*
> handle the following foramts:
> n/d
> n
> */
> T n, d;
> char c = 0; // for '/'
> is >> n;
> if (is.good()) {
> is.get(c);
> }
> if (c == '/') { // fraction
> if (is.good())
> is >> d;
> }
> else if (std::isspace(c) || is.rdstate() & std::ios_base::eofbit)
> { // whole number
> d = 1;
> }
> else {
> is.clear(std::ios_base::badbit); // set state
> }
> if (is) // everything is good
> r = rational<T>(n, d);
> return is;
> }


> I know, my code may be inefficient.
> Any suggestion for better/more elegant handling different
> formats and better efficiency?


I'm not too sure about your error handling, and your logic. If
nothing else, you're extracting one character too many when
reading just a whole number. (Think of something like 3+1/3.)
What's wrong with something simple like:

T n;
is >> n;
T d(1); // T must support conversion from int.
if ( is.peek() == '/' ) {
is.get(); // extract '/'
is >> d;
}
if ( is ) {
r = rational<T>( n, d );
}
return is;

This leaves all of the error handling up to >>T, and seems
overall the simplest solution.

--
James Kanze
 
Reply With Quote
 
 
 
 
Saeed Amrollahi
Guest
Posts: n/a
 
      11-16-2009
On Nov 16, 12:01*pm, James Kanze <james.ka...@gmail.com> wrote:
> On Nov 15, 4:07 pm, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:
>
>
>
>
>
> > I am going to design and implement a typical library for
> > rational numbers, something like Boost.Rational. My class is
> > actually implemented as a template, in a similar manner to the
> > standard complex class. *I want to handle Whole numbers like
> > rational numbers; As you know, from point of math view whole
> > numbers are subset of rational numbers, for example 3 is 3/1.
> > I like to read both kind of numbers (whole and fraction) in a
> > single operator>> function. I mean I want to handle
> > * a
> > * a/b
> > together. I finally ended with an assumption: Immediately,
> > after numerator, I should get '/':
> > template<class T>
> > std::istream& operator>>(std::istream& is, rational<T>& r)
> > {
> > * /*
> > * * handle the following foramts:
> > * * n/d
> > * * n
> > * */
> > * T n, d;
> > * char c = 0; // for '/'
> > * is >> n;
> > * if (is.good()) {
> > * * is.get(c);
> > * }
> > * if (c == '/') { // fraction
> > * * if (is.good())
> > * * * * is >> d;
> > * }
> > *else if (std::isspace(c) || is.rdstate() & std::ios_base::eofbit)
> > { // whole number
> > * * d = 1;
> > * }
> > * else {
> > * * is.clear(std::ios_base::badbit); // set state
> > * }
> > * if (is) // everything is good
> > * * r = rational<T>(n, d);
> > * return is;
> > }
> > I know, my code may be inefficient.
> > Any suggestion for better/more elegant handling different
> > formats and better efficiency?

>
> I'm not too sure about your error handling, and your logic. *If
> nothing else, you're extracting one character too many when
> reading just a whole number. *(Think of something like 3+1/3.)
> What's wrong with something simple like:
>
> * * T n;
> * * is >> n;
> * * T d(1); * *// *T must support conversion from int.
> * * if ( is.peek() == '/' ) {
> * * * * is.get(); * * * // *extract '/'
> * * * * is >> d;
> * * }
> * * if ( is ) {
> * * * * r = rational<T>( n, d );
> * * }
> * * return is;
>
> This leaves all of the error handling up to >>T, and seems
> overall the simplest solution.
>
> --
> James Kanze- Hide quoted text -
>
> - Show quoted text -


Hi James
Thank you for your feedback.
The template parameter T is an Integral type.
My main problem is:
Is there any solution to read a fraction and whole number in formatted
way
rather than using unformatted (get function)? I guess there is no way.
So I assumed, if user wants to enter a whole number, (s)he have to
enter in
one line. So, I use isspace() and ios_base::eofbit.
for a fraction my assumption is: if user wants to enter a fraction, (s)
he have to
enter '/' immediately after numerator. Your code somehow reflects
that.
Of course your code is simple and elegant and my code is somehow
sloppy.

Please throw light.
-- Saeed Amrollahi
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      11-16-2009
On Nov 16, 9:26 am, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:
> On Nov 16, 12:01 pm, James Kanze <james.ka...@gmail.com> wrote:


[...]
> > I'm not too sure about your error handling, and your logic.
> > If nothing else, you're extracting one character too many
> > when reading just a whole number. (Think of something like
> > 3+1/3.) What's wrong with something simple like:


> > T n;
> > is >> n;
> > T d(1); // T must support conversion from int.
> > if ( is.peek() == '/' ) {
> > is.get(); // extract '/'
> > is >> d;
> > }
> > if ( is ) {
> > r = rational<T>( n, d );
> > }
> > return is;


> > This leaves all of the error handling up to >>T, and seems
> > overall the simplest solution.



> Thank you for your feedback.
> The template parameter T is an Integral type.


I more or less guessed that. Although you might want to ask
yourself what will happen if someone instantiates your template
on double, or even std::string.

> My main problem is:
> Is there any solution to read a fraction and whole number in
> formatted way rather than using unformatted (get function)?


I'm not sure what you really mean by "formatted" way? You want
to look at a single character, without extracting it;
istream:eek is the function which does that.

There is one weakness in my quicky solution above: it doesn't
allow white space before the '/', but allows it after. This
could easily be fixed by verifying that the character after the
'/' is not white space (getting it, again, using peek()), or by
skipping white space before checking for the '/'.

> I guess there is no way. So I assumed, if user wants to enter
> a whole number, (s)he have to enter in one line.


Not with the above. The above will read a number. If the
character immediately following the number is a '/', it skips
this, and reads a second number. Otherwise, it stops with the
number, removing no more characters.

> So, I use isspace() and ios_base::eofbit.


That was the point I didn't fully understand in the original
code. Is the fact that you only read the numerator (and use 1
for the denominator) determined by the fact that the first
number is immediately followed by a '/', or by the fact that it
was followed by white space or the end of file. In other words,
what was the desired behavior when reading something like:
43,x
Should the extractor extract the 43, return 43/1, and leave the
input positionned on the ',', or should it set failbit to
indicate a format error on input. (My version does the first.)

> for a fraction my assumption is: if user wants to enter a
> fraction, (s) he have to enter '/' immediately after
> numerator. Your code somehow reflects that.


My code does that exactly. If the first character after the
number in the stream is a '/', it skips it, and attempts to read
a denominator. Otherwise, it uses the default value 1 as
denominator.

--
James Kanze
 
Reply With Quote
 
Saeed Amrollahi
Guest
Posts: n/a
 
      11-17-2009
On Nov 16, 9:20*pm, James Kanze <james.ka...@gmail.com> wrote:
> On Nov 16, 9:26 am, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:
>
> > On Nov 16, 12:01 pm, James Kanze <james.ka...@gmail.com> wrote:

>
> * * [...]
>
>
>
>
>
> > > I'm not too sure about your error handling, and your logic.
> > > If nothing else, you're extracting one character too many
> > > when reading just a whole number. *(Think of something like
> > > 3+1/3.) What's wrong with something simple like:
> > > * * T n;
> > > * * is >> n;
> > > * * T d(1); * *// *T must support conversion from int.
> > > * * if ( is.peek() == '/' ) {
> > > * * * * is.get(); * * * // *extract '/'
> > > * * * * is >> d;
> > > * * }
> > > * * if ( is ) {
> > > * * * * r = rational<T>( n, d );
> > > * * }
> > > * * return is;
> > > This leaves all of the error handling up to >>T, and seems
> > > overall the simplest solution.

> > Thank you for your feedback.
> > The template parameter T is an Integral type.

>
> I more or less guessed that. *Although you might want to ask
> yourself what will happen if someone instantiates your template
> on double, or even std::string.
>
> > My main problem is:
> > Is there any solution to read a fraction and whole number in
> > formatted way rather than using unformatted (get function)?

>
> I'm not sure what you really mean by "formatted" way? *You want
> to look at a single character, without extracting it;
> istream:eek is the function which does that.
>
> There is one weakness in my quicky solution above: it doesn't
> allow white space before the '/', but allows it after. *This
> could easily be fixed by verifying that the character after the
> '/' is not white space (getting it, again, using peek()), or by
> skipping white space before checking for the '/'.
>
> > I guess there is no way. *So I assumed, if user wants to enter
> > a whole number, (s)he have to enter in one line.

>
> Not with the above. *The above will read a number. *If the
> character immediately following the number is a '/', it skips
> this, and reads a second number. *Otherwise, it stops with the
> number, removing no more characters.
>
> > So, I use isspace() and ios_base::eofbit.

>
> That was the point I didn't fully understand in the original
> code. *Is the fact that you only read the numerator (and use 1
> for the denominator) determined by the fact that the first
> number is immediately followed by a '/', or by the fact that it
> was followed by white space or the end of file. *In other words,
> what was the desired behavior when reading something like:
> * * 43,x
> Should the extractor extract the 43, return 43/1, and leave the
> input positionned on the ',', or should it set failbit to
> indicate a format error on input. *(My version does the first.)
>
> > for a fraction my assumption is: if user wants to enter a
> > fraction, (s) he have to enter '/' immediately after
> > numerator. Your code somehow reflects that.

>
> My code does that exactly. *If the first character after the
> number in the stream is a '/', it skips it, and attempts to read
> a denominator. *Otherwise, it uses the default value 1 as
> denominator.
>
> --
> James Kanze- Hide quoted text -
>
> - Show quoted text -


Thanks for your feedback
-- Saeed Amrollahi
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Rational Numbers Facundo Batista Python 15 01-14-2007 01:21 PM
Re: Rational Numbers Facundo Batista Python 3 01-13-2007 09:59 AM
rational numbers Paul Rubin Python 3 01-17-2006 06:01 PM
Re: precision problems in base conversion of rational numbers Brian van den Broek Python 4 07-07-2005 05:07 PM
precision problems in base conversion of rational numbers Brian van den Broek Python 2 07-05-2005 07:50 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57