Design of Rational number library

  • Thread starter Saeed Amrollahi
  • Start date
S

Saeed Amrollahi

Hi

I began to define a pilot project by myself. It is design and
implementation of
runtime Rational number.
I decided to take the complex numbers in library as a model, because
I thought the design of complex numbers is similar to rational numbers
at least
from point of class design view. Up until now, I experienced a few
problem,
but I want to know your opinion and some guideline about the most
subtle one.
As you know the complex numbers are DefaultConstructible:

template<class T>
class complex {
public:
complex(const T& = T(), const T& = T()); // constructor
// ...
};

with above constructor, you can create Zero (without parameter),
real numbers (with one parameter) and complex number (two parameters).
It is obvious, the rational numbers should be DefaultConstructible,
so like complex numbers I tries to define the rational number like
this:

template<class T>
class rational { // generic rational number
public:
rational(const T& = T(), const T& = /* the representation of "One"
in T */); // constructor
// ...
};

The problem is: How to represent One for Denominator in a Generic
manner?
Of course some libraries like Boost.Rational make the assumption
the template parameter is integral type. But it is not generic, I want
to have rational<bool>, rationa<int>, rational<float>,
rational<double>
, rational<complex>, rational<rational> and ...
Please throw light on the problem.
Also, what is your opinion about multiple constructors vs. single
constructor with default argument:
Rational(const T& = T(), const T& = /* the representation of "One"
in T */);
and
Rational();
Rational(const T&);
Rational(const T&, const T&);

Regards,
-- Saeed Amrollahi

P.S. Is it good idea to send the post to comp.lang.c++.moderated too.
 
S

SG

I began to define a pilot project by myself. It is design and
implementation of runtime Rational number.
[...]

template<class T>
class rational { // generic rational number
public:
rational(const T& = T(), const T& = /* the representation of "One"
in T */); // constructor
// ...
};

The problem is: How to represent One for Denominator in a Generic
manner?
Of course some libraries like Boost.Rational make the assumption
the template parameter is integral type.

Do they? I would have guessed that the only assumption made is that an
integer is explicitly convertible to T -- which is a rather reasonable
assumption. In that case you can write

template<class T>
class rational
{
public:
rational(const T& = T(), const T& = T(1));
.....
};
But it is not generic, I want
to have rational<bool>,

What's the point of rational said:
rational<float>, rational<double>,
rational<complex>, rational<rational>

What's the point of those? Doesn't it make more sense to restrict T to
types that behave like signed integral types?

Cheers!
SG
 
B

Bart van Ingen Schenau

It is obvious, the rational numbers should be DefaultConstructible,
so like complex numbers I tries to define the rational number like
this:

template<class T>
class rational { // generic rational number
public:
  rational(const T& = T(), const T& = /* the representation of "One"
in T */); // constructor
  // ...

};

The problem is: How to represent One for Denominator in a Generic
manner?
Of course some libraries like Boost.Rational make the assumption
the template parameter is integral type. But it is not generic, I want
to have rational<bool>, rationa<int>, rational<float>,
rational<double>
, rational<complex>, rational<rational> and ...
Please throw light on the problem.

If you want to go down that road, why are you forcing the numerator
and denominator to have the same type?
And can you reasonably still call this: rational<mymath::matrix> a
Rational number?
And what about rational<std::string>? Where do you draw the line in
what is acceptable as your template argument.

If your rational class-template is meant to model the mathematical
group of Rational numbers (Q), then it is sufficient if you can use
only the integer types as template parameter, because that is how the
group is defined in mathematics: Each Rational number can be written
as the quotient of two integers.
Also, what is your opinion about multiple constructors vs. single
constructor with default argument:
   Rational(const T& = T(), const T& = /* the representation of "One"
in T */);
and
  Rational();
  Rational(const T&);
  Rational(const T&, const T&);

If 'Rational r(10, 1)' and 'Rational r(10)' must have exactly the same
effect, then it is preferable to use only one constructor with a
default argument. The reason is that the other option leads to code
duplication and possibly bugs that are fixed in one constructor but
not in the other.
Regards,
  -- Saeed Amrollahi
Bart v Ingen Schenau
 
S

Saeed Amrollahi

I began to define a pilot project by myself. It is design and
implementation of runtime Rational number.
[...]

template<class T>
class rational { // generic rational number
public:
  rational(const T& = T(), const T& = /* the representation of "One"
in T */); // constructor
  // ...
};
The problem is: How to represent One for Denominator in a Generic
manner?
Of course some libraries like Boost.Rational make the assumption
the template parameter is integral type.

Do they? I would have guessed that the only assumption made is that an
integer is explicitly convertible to T -- which is a rather reasonable
assumption. In that case you can write

  template<class T>
  class rational
  {
  public:
    rational(const T& = T(), const T& = T(1));
    .....
  };
But it is not generic, I want
to have rational<bool>,

What's the point of rational said:
rational<float>, rational<double>,
rational<complex>, rational<rational>

What's the point of those? Doesn't it make more sense to restrict T to
types that behave like signed integral types?

Cheers!
SG

Hi

Thanks for your feedback. Of course some members of C++ standard
committee have your
opinion. May be such generality has no gain. I know form point of math
view, the numerator and denominator
of a rational number should be integer, but I think in programming
world, there are some
applications for float or double or boot rationals.

About Boost.Rational, I mean the template parameter is numeric type:
template<typename I> class rational {
typedef implementation-defined bool_type;

public:
typedef I int_type;

// Constructors
rational(); // Zero
rational(I n); // Equal to n/1
rational(I n, I d); // General case (n/d)
// ...
};

and of course I don't know your opinion about Single constructor vs.
Multiple constructors.

Thanks,
-- Saeed Amrollahi
 
S

Saeed Amrollahi

If you want to go down that road, why are you forcing the numerator
and denominator to have the same type?
And can you reasonably still call this: rational<mymath::matrix> a
Rational number?
And what about rational<std::string>? Where do you draw the line in
what is acceptable as your template argument.

If your rational class-template is meant to model the mathematical
group of Rational numbers (Q), then it is sufficient if you can use
only the integer types as template parameter, because that is how the
group is defined in mathematics: Each Rational number can be written
as the quotient of two integers.


If 'Rational r(10, 1)' and 'Rational r(10)' must have exactly the same
effect, then it is preferable to use only one constructor with a
default argument. The reason is that the other option leads to code
duplication and possibly bugs that are fixed in one constructor but
not in the other.




Bart v Ingen Schenau- Hide quoted text -

- Show quoted text -

Hi

Thanks for your feedback. May be such generality is not applicable
regarding to mathematics definition
and real world usage.

About Single constructor vs. Multiple constructors decision, someone
from C++ standard committee is favoring
multiple constructor, because the default argument should be created
each time, the constructor is called
and for the case of nontrivial argument. may be it isn't efficient.

Regards,
-- Saeed Amrollahi
 

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

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top