Design of Rational number library

Discussion in 'C++' started by Saeed Amrollahi, Sep 4, 2009.

  1. 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.
     
    Saeed Amrollahi, Sep 4, 2009
    #1
    1. Advertising

  2. Saeed Amrollahi

    SG Guest

    On 4 Sep., 11:50, Saeed Amrollahi wrote:

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

    > 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
     
    SG, Sep 4, 2009
    #2
    1. Advertising

  3. On Sep 4, 11:50 am, Saeed Amrollahi <> wrote:
    > 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
     
    Bart van Ingen Schenau, Sep 4, 2009
    #3
  4. On Sep 4, 3:21 pm, SG <> wrote:
    > On 4 Sep., 11:50, Saeed Amrollahi wrote:
    >
    > > 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<bool> ?
    >
    > > 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
     
    Saeed Amrollahi, Sep 4, 2009
    #4
  5. On Sep 4, 3:34 pm, Bart van Ingen Schenau <>
    wrote:
    > On Sep 4, 11:50 am, Saeed Amrollahi <> wrote:
    >
    >
    >
    >
    >
    > > 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- 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
     
    Saeed Amrollahi, Sep 4, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jenny

    Rational

    Jenny, Aug 22, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    518
    Kevin Spencer
    Aug 22, 2003
  2. Replies:
    7
    Views:
    336
    Gabriel G
    Nov 1, 2006
  3. Lie
    Replies:
    25
    Views:
    745
    Dafydd Hughes
    Dec 18, 2007
  4. Saeed Amrollahi

    Design of Rational number library

    Saeed Amrollahi, Sep 4, 2009, in forum: C++
    Replies:
    8
    Views:
    384
    Francesco
    Sep 7, 2009
  5. Dave Burt
    Replies:
    6
    Views:
    146
    Dave Burt
    May 12, 2005
Loading...

Share This Page