Class: Rational

Inherits:
Numeric show all
Defined in:
rational.c

Overview

A rational number can be represented as a paired integer number; a/b (b>0). Where a is numerator and b is denominator. Integer a equals rational a/1 mathematically.

In ruby, you can create rational object with Rational or to_r method. The return values will be irreducible.

Rational(1)      #=> (1/1)
Rational(2, 3)   #=> (2/3)
Rational(4, -6)  #=> (-2/3)
3.to_r           #=> (3/1)

You can also create rational object from floating-point numbers or strings.

Rational(0.3)    #=> (5404319552844595/18014398509481984)
Rational('0.3')  #=> (3/10)
Rational('2/3')  #=> (2/3)

0.3.to_r         #=> (5404319552844595/18014398509481984)
'0.3'.to_r       #=> (3/10)
'2/3'.to_r       #=> (2/3)

A rational object is an exact number, which helps you to write program without any rounding errors.

10.times.inject(0){|t,| t + 0.1}              #=> 0.9999999999999999
10.times.inject(0){|t,| t + Rational('0.1')}  #=> (1/1)

However, when an expression has inexact factor (numerical value or operation), will produce an inexact result.

Rational(10) / 3   #=> (10/3)
Rational(10) / 3.0 #=> 3.3333333333333335

Rational(-8) ** Rational(1, 3)
                   #=> (1.0000000000000002+1.7320508075688772i)

Instance Method Summary collapse

Methods inherited from Numeric

#%, #+@, #-@, #abs, #abs2, #angle, #arg, #conj, #conjugate, #div, #divmod, #eql?, #i, #imag, #imaginary, #initialize_copy, #integer?, #magnitude, #modulo, #nonzero?, #phase, #polar, #real, #real?, #rect, #rectangular, #remainder, #singleton_method_added, #step, #to_c, #to_int, #zero?

Methods included from Comparable

#<, #<=, #>, #>=, #between?

Instance Method Details

#*(numeric) ⇒ Object

Performs multiplication.

For example:

Rational(2, 3)  * Rational(2, 3)   #=> (4/9)
Rational(900)   * Rational(1)      #=> (900/1)
Rational(-2, 9) * Rational(-9, 2)  #=> (1/1)
Rational(9, 8)  * 4                #=> (9/2)
Rational(20, 9) * 9.8              #=> 21.77777777777778


# File 'rational.c'

/*
 * call-seq:
 *    rat * numeric  ->  numeric_result
 *
 * Performs multiplication.
 *
 * For example:
 *
 *    Rational(2, 3)  * Rational(2, 3)   #=> (4/9)
 *    Rational(900)   * Rational(1)      #=> (900/1)
 *    Rational(-2, 9) * Rational(-9, 2)  #=> (1/1)
 *    Rational(9, 8)  * 4                #=> (9/2)
 *    Rational(20, 9) * 9.8              #=> 21.77777777777778
 */
static VALUE
nurat_mul(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
    {
        get_dat1(self);

        return f_muldiv(self,
                dat->num, dat->den,
                other, ONE, '*');
    }
      case T_FLOAT:
    return f_mul(f_to_f(self), other);
      case T_RATIONAL:
    {
        get_dat2(self, other);

        return f_muldiv(self,
                adat->num, adat->den,
                bdat->num, bdat->den, '*');
    }
      default:
    return rb_num_coerce_bin(self, other, '*');
    }
}

#**(numeric) ⇒ Object

Performs exponentiation.

For example:

Rational(2)    ** Rational(3)    #=> (8/1)
Rational(10)   ** -2             #=> (1/100)
Rational(10)   ** -2.0           #=> 0.01
Rational(-4)   ** Rational(1,2)  #=> (1.2246063538223773e-16+2.0i)
Rational(1, 2) ** 0              #=> (1/1)
Rational(1, 2) ** 0.0            #=> 1.0


# File 'rational.c'

/*
 * call-seq:
 *    rat ** numeric  ->  numeric_result
 *
 * Performs exponentiation.
 *
 * For example:
 *
 *    Rational(2)    ** Rational(3)    #=> (8/1)
 *    Rational(10)   ** -2             #=> (1/100)
 *    Rational(10)   ** -2.0           #=> 0.01
 *    Rational(-4)   ** Rational(1,2)  #=> (1.2246063538223773e-16+2.0i)
 *    Rational(1, 2) ** 0              #=> (1/1)
 *    Rational(1, 2) ** 0.0            #=> 1.0
 */
static VALUE
nurat_expt(VALUE self, VALUE other)
{
    if (k_exact_zero_p(other))
    return f_rational_new_bang1(CLASS_OF(self), ONE);

    if (k_rational_p(other)) {
    get_dat1(other);

    if (f_one_p(dat->den))
        other = dat->num; /* c14n */
    }

    switch (TYPE(other)) {
      case T_FIXNUM:
    {
        VALUE num, den;

        get_dat1(self);

        switch (FIX2INT(f_cmp(other, ZERO))) {
          case 1:
        num = f_expt(dat->num, other);
        den = f_expt(dat->den, other);
        break;
          case -1:
        num = f_expt(dat->den, f_negate(other));
        den = f_expt(dat->num, f_negate(other));
        break;
          default:
        num = ONE;
        den = ONE;
        break;
        }
        return f_rational_new2(CLASS_OF(self), num, den);
    }
      case T_BIGNUM:
    rb_warn("in a**b, b may be too big");
    /* fall through */
      case T_FLOAT:
      case T_RATIONAL:
    return f_expt(f_to_f(self), other);
      default:
    return rb_num_coerce_bin(self, other, id_expt);
    }
}

#+(numeric) ⇒ Object

Performs addition.

For example:

Rational(2, 3)  + Rational(2, 3)   #=> (4/3)
Rational(900)   + Rational(1)      #=> (900/1)
Rational(-2, 9) + Rational(-9, 2)  #=> (-85/18)
Rational(9, 8)  + 4                #=> (41/8)
Rational(20, 9) + 9.8              #=> 12.022222222222222


# File 'rational.c'

/*
 * call-seq:
 *    rat + numeric  ->  numeric_result
 *
 * Performs addition.
 *
 * For example:
 *
 *    Rational(2, 3)  + Rational(2, 3)   #=> (4/3)
 *    Rational(900)   + Rational(1)      #=> (900/1)
 *    Rational(-2, 9) + Rational(-9, 2)  #=> (-85/18)
 *    Rational(9, 8)  + 4                #=> (41/8)
 *    Rational(20, 9) + 9.8              #=> 12.022222222222222
 */
static VALUE
nurat_add(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
    {
        get_dat1(self);

        return f_addsub(self,
                dat->num, dat->den,
                other, ONE, '+');
    }
      case T_FLOAT:
    return f_add(f_to_f(self), other);
      case T_RATIONAL:
    {
        get_dat2(self, other);

        return f_addsub(self,
                adat->num, adat->den,
                bdat->num, bdat->den, '+');
    }
      default:
    return rb_num_coerce_bin(self, other, '+');
    }
}

#-(numeric) ⇒ Object

Performs subtraction.

For example:

Rational(2, 3)  - Rational(2, 3)   #=> (0/1)
Rational(900)   - Rational(1)      #=> (899/1)
Rational(-2, 9) - Rational(-9, 2)  #=> (77/18)
Rational(9, 8)  - 4                #=> (23/8)
Rational(20, 9) - 9.8              #=> -7.577777777777778


# File 'rational.c'

/*
 * call-seq:
 *    rat - numeric  ->  numeric_result
 *
 * Performs subtraction.
 *
 * For example:
 *
 *    Rational(2, 3)  - Rational(2, 3)   #=> (0/1)
 *    Rational(900)   - Rational(1)      #=> (899/1)
 *    Rational(-2, 9) - Rational(-9, 2)  #=> (77/18)
 *    Rational(9, 8)  - 4                #=> (23/8)
 *    Rational(20, 9) - 9.8              #=> -7.577777777777778
 */
static VALUE
nurat_sub(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
    {
        get_dat1(self);

        return f_addsub(self,
                dat->num, dat->den,
                other, ONE, '-');
    }
      case T_FLOAT:
    return f_sub(f_to_f(self), other);
      case T_RATIONAL:
    {
        get_dat2(self, other);

        return f_addsub(self,
                adat->num, adat->den,
                bdat->num, bdat->den, '-');
    }
      default:
    return rb_num_coerce_bin(self, other, '-');
    }
}

#/(numeric) ⇒ Object #quo(numeric) ⇒ Object

Performs division.

For example:

Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
Rational(900)   / Rational(1)      #=> (900/1)
Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
Rational(9, 8)  / 4                #=> (9/32)
Rational(20, 9) / 9.8              #=> 0.22675736961451246


# File 'rational.c'

/*
 * call-seq:
 *    rat / numeric     ->  numeric_result
 *    rat.quo(numeric)  ->  numeric_result
 *
 * Performs division.
 *
 * For example:
 *
 *    Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
 *    Rational(900)   / Rational(1)      #=> (900/1)
 *    Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
 *    Rational(9, 8)  / 4                #=> (9/32)
 *    Rational(20, 9) / 9.8              #=> 0.22675736961451246
 */
static VALUE
nurat_div(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
    if (f_zero_p(other))
        rb_raise_zerodiv();
    {
        get_dat1(self);

        return f_muldiv(self,
                dat->num, dat->den,
                other, ONE, '/');
    }
      case T_FLOAT:
    return rb_funcall(f_to_f(self), '/', 1, other);
      case T_RATIONAL:
    if (f_zero_p(other))
        rb_raise_zerodiv();
    {
        get_dat2(self, other);

        if (f_one_p(self))
        return f_rational_new_no_reduce2(CLASS_OF(self),
                         bdat->den, bdat->num);

        return f_muldiv(self,
                adat->num, adat->den,
                bdat->num, bdat->den, '/');
    }
      default:
    return rb_num_coerce_bin(self, other, '/');
    }
}

#//Object

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_idiv(VALUE self, VALUE other)
{
    return f_idiv(self, other);
}

#<=>(numeric) ⇒ -1, ...

Performs comparison and returns -1, 0, or +1.

For example:

Rational(2, 3)  <=> Rational(2, 3)  #=> 0
Rational(5)     <=> 5               #=> 0
Rational(2,3)   <=> Rational(1,3)   #=> 1
Rational(1,3)   <=> 1               #=> -1
Rational(1,3)   <=> 0.3             #=> 1

Returns:

  • (-1, 0, +1, nil)


# File 'rational.c'

/*
 * call-seq:
 *    rat <=> numeric  ->  -1, 0, +1 or nil
 *
 * Performs comparison and returns -1, 0, or +1.
 *
 * For example:
 *
 *    Rational(2, 3)  <=> Rational(2, 3)  #=> 0
 *    Rational(5)     <=> 5               #=> 0
 *    Rational(2,3)   <=> Rational(1,3)   #=> 1
 *    Rational(1,3)   <=> 1               #=> -1
 *    Rational(1,3)   <=> 0.3             #=> 1
 */
static VALUE
nurat_cmp(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
    {
        get_dat1(self);

        if (FIXNUM_P(dat->den) && FIX2LONG(dat->den) == 1)
        return f_cmp(dat->num, other); /* c14n */
        return f_cmp(self, f_rational_new_bang1(CLASS_OF(self), other));
    }
      case T_FLOAT:
    return f_cmp(f_to_f(self), other);
      case T_RATIONAL:
    {
        VALUE num1, num2;

        get_dat2(self, other);

        if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
        FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
        num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
        num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
        }
        else {
        num1 = f_mul(adat->num, bdat->den);
        num2 = f_mul(bdat->num, adat->den);
        }
        return f_cmp(f_sub(num1, num2), ZERO);
    }
      default:
    return rb_num_coerce_cmp(self, other, id_cmp);
    }
}

#==(object) ⇒ Boolean

Returns true if rat equals object numerically.

For example:

Rational(2, 3)  == Rational(2, 3)   #=> true
Rational(5)     == 5                #=> true
Rational(0)     == 0.0              #=> true
Rational('1/3') == 0.33             #=> false
Rational('1/2') == '1/2'            #=> false

Returns:

  • (Boolean)


# File 'rational.c'

/*
 * call-seq:
 *    rat == object  ->  true or false
 *
 * Returns true if rat equals object numerically.
 *
 * For example:
 *
 *    Rational(2, 3)  == Rational(2, 3)   #=> true
 *    Rational(5)     == 5                #=> true
 *    Rational(0)     == 0.0              #=> true
 *    Rational('1/3') == 0.33             #=> false
 *    Rational('1/2') == '1/2'            #=> false
 */
static VALUE
nurat_eqeq_p(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
    {
        get_dat1(self);

        if (f_zero_p(dat->num) && f_zero_p(other))
        return Qtrue;

        if (!FIXNUM_P(dat->den))
        return Qfalse;
        if (FIX2LONG(dat->den) != 1)
        return Qfalse;
        if (f_eqeq_p(dat->num, other))
        return Qtrue;
        return Qfalse;
    }
      case T_FLOAT:
    return f_eqeq_p(f_to_f(self), other);
      case T_RATIONAL:
    {
        get_dat2(self, other);

        if (f_zero_p(adat->num) && f_zero_p(bdat->num))
        return Qtrue;

        return f_boolcast(f_eqeq_p(adat->num, bdat->num) &&
                  f_eqeq_p(adat->den, bdat->den));
    }
      default:
    return f_eqeq_p(other, self);
    }
}

#ceilInteger #ceil(precision = 0) ⇒ Object

Returns the truncated value (toward positive infinity).

For example:

Rational(3).ceil      #=> 3
Rational(2, 3).ceil   #=> 1
Rational(-3, 2).ceil  #=> -1

       decimal      -  1  2  3 . 4  5  6
                      ^  ^  ^  ^   ^  ^
      precision      -3 -2 -1  0  +1 +2

'%f' % Rational('-123.456').ceil(+1)  #=> "-123.400000"
'%f' % Rational('-123.456').ceil(-1)  #=> "-120.000000"

Overloads:



# File 'rational.c'

/*
 * call-seq:
 *    rat.ceil               ->  integer
 *    rat.ceil(precision=0)  ->  rational
 *
 * Returns the truncated value (toward positive infinity).
 *
 * For example:
 *
 *    Rational(3).ceil      #=> 3
 *    Rational(2, 3).ceil   #=> 1
 *    Rational(-3, 2).ceil  #=> -1
 *
 *           decimal      -  1  2  3 . 4  5  6
 *                          ^  ^  ^  ^   ^  ^
 *          precision      -3 -2 -1  0  +1 +2
 *
 *    '%f' % Rational('-123.456').ceil(+1)  #=> "-123.400000"
 *    '%f' % Rational('-123.456').ceil(-1)  #=> "-120.000000"
 */
static VALUE
nurat_ceil_n(int argc, VALUE *argv, VALUE self)
{
    return f_round_common(argc, argv, self, nurat_ceil);
}

#coerceObject

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_coerce(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
    return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
      case T_FLOAT:
    return rb_assoc_new(other, f_to_f(self));
      case T_RATIONAL:
    return rb_assoc_new(other, self);
      case T_COMPLEX:
    if (k_exact_zero_p(RCOMPLEX(other)->imag))
        return rb_assoc_new(f_rational_new_bang1
                (CLASS_OF(self), RCOMPLEX(other)->real), self);
    }

    rb_raise(rb_eTypeError, "%s can't be coerced into %s",
         rb_obj_classname(other), rb_obj_classname(self));
    return Qnil;
}

#denominatorInteger

Returns the denominator (always positive).

For example:

Rational(7).denominator             #=> 1
Rational(7, 1).denominator          #=> 1
Rational(9, -4).denominator         #=> 4
Rational(-2, -10).denominator       #=> 5
rat.numerator.gcd(rat.denominator)  #=> 1

Returns:



# File 'rational.c'

/*
 * call-seq:
 *    rat.denominator  ->  integer
 *
 * Returns the denominator (always positive).
 *
 * For example:
 *
 *    Rational(7).denominator             #=> 1
 *    Rational(7, 1).denominator          #=> 1
 *    Rational(9, -4).denominator         #=> 4
 *    Rational(-2, -10).denominator       #=> 5
 *    rat.numerator.gcd(rat.denominator)  #=> 1
 */
static VALUE
nurat_denominator(VALUE self)
{
    get_dat1(self);
    return dat->den;
}

#exact?Object

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_true(VALUE self)
{
    return Qtrue;
}

#fdiv(numeric) ⇒ Float

Performs division and returns the value as a float.

For example:

Rational(2, 3).fdiv(1)       #=> 0.6666666666666666
Rational(2, 3).fdiv(0.5)     #=> 1.3333333333333333
Rational(2).fdiv(3)          #=> 0.6666666666666666

Returns:



# File 'rational.c'

/*
 * call-seq:
 *    rat.fdiv(numeric)  ->  float
 *
 * Performs division and returns the value as a float.
 *
 * For example:
 *
 *    Rational(2, 3).fdiv(1)       #=> 0.6666666666666666
 *    Rational(2, 3).fdiv(0.5)     #=> 1.3333333333333333
 *    Rational(2).fdiv(3)          #=> 0.6666666666666666
 */
static VALUE
nurat_fdiv(VALUE self, VALUE other)
{
    if (f_zero_p(other))
    return f_div(self, f_to_f(other));
    return f_to_f(f_div(self, other));
}

#floorInteger #floor(precision = 0) ⇒ Object

Returns the truncated value (toward negative infinity).

For example:

Rational(3).floor      #=> 3
Rational(2, 3).floor   #=> 0
Rational(-3, 2).floor  #=> -1

       decimal      -  1  2  3 . 4  5  6
                      ^  ^  ^  ^   ^  ^
      precision      -3 -2 -1  0  +1 +2

'%f' % Rational('-123.456').floor(+1)  #=> "-123.500000"
'%f' % Rational('-123.456').floor(-1)  #=> "-130.000000"

Overloads:



# File 'rational.c'

/*
 * call-seq:
 *    rat.floor               ->  integer
 *    rat.floor(precision=0)  ->  rational
 *
 * Returns the truncated value (toward negative infinity).
 *
 * For example:
 *
 *    Rational(3).floor      #=> 3
 *    Rational(2, 3).floor   #=> 0
 *    Rational(-3, 2).floor  #=> -1
 *
 *           decimal      -  1  2  3 . 4  5  6
 *                          ^  ^  ^  ^   ^  ^
 *          precision      -3 -2 -1  0  +1 +2
 *
 *    '%f' % Rational('-123.456').floor(+1)  #=> "-123.500000"
 *    '%f' % Rational('-123.456').floor(-1)  #=> "-130.000000"
 */
static VALUE
nurat_floor_n(int argc, VALUE *argv, VALUE self)
{
    return f_round_common(argc, argv, self, nurat_floor);
}

#hashObject

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_hash(VALUE self)
{
    st_index_t v, h[2];
    VALUE n;

    get_dat1(self);
    n = rb_hash(dat->num);
    h[0] = NUM2LONG(n);
    n = rb_hash(dat->den);
    h[1] = NUM2LONG(n);
    v = rb_memhash(h, sizeof(h));
    return LONG2FIX(v);
}

#inspectString

Returns the value as a string for inspection.

For example:

Rational(2).inspect      #=> "(2/1)"
Rational(-8, 6).inspect  #=> "(-4/3)"
Rational('0.5').inspect  #=> "(1/2)"

Returns:



# File 'rational.c'

/*
 * call-seq:
 *    rat.inspect  ->  string
 *
 * Returns the value as a string for inspection.
 *
 * For example:
 *
 *    Rational(2).inspect      #=> "(2/1)"
 *    Rational(-8, 6).inspect  #=> "(-4/3)"
 *    Rational('0.5').inspect  #=> "(1/2)"
 */
static VALUE
nurat_inspect(VALUE self)
{
    VALUE s;

    s = rb_usascii_str_new2("(");
    rb_str_concat(s, f_format(self, f_inspect));
    rb_str_cat2(s, ")");

    return s;
}

#marshal_dumpObject

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_marshal_dump(VALUE self)
{
    VALUE a;
    get_dat1(self);

    a = rb_assoc_new(dat->num, dat->den);
    rb_copy_generic_ivar(a, self);
    return a;
}

#marshal_loadObject

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_marshal_load(VALUE self, VALUE a)
{
    get_dat1(self);
    Check_Type(a, T_ARRAY);
    dat->num = RARRAY_PTR(a)[0];
    dat->den = RARRAY_PTR(a)[1];
    rb_copy_generic_ivar(self, a);

    if (f_zero_p(dat->den))
    rb_raise_zerodiv();

    return self;
}

#numeratorInteger

Returns the numerator.

For example:

Rational(7).numerator        #=> 7
Rational(7, 1).numerator     #=> 7
Rational(9, -4).numerator    #=> -9
Rational(-2, -10).numerator  #=> 1

Returns:



# File 'rational.c'

/*
 * call-seq:
 *    rat.numerator  ->  integer
 *
 * Returns the numerator.
 *
 * For example:
 *
 *    Rational(7).numerator        #=> 7
 *    Rational(7, 1).numerator     #=> 7
 *    Rational(9, -4).numerator    #=> -9
 *    Rational(-2, -10).numerator  #=> 1
 */
static VALUE
nurat_numerator(VALUE self)
{
    get_dat1(self);
    return dat->num;
}

#/(numeric) ⇒ Object #quo(numeric) ⇒ Object

Performs division.

For example:

Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
Rational(900)   / Rational(1)      #=> (900/1)
Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
Rational(9, 8)  / 4                #=> (9/32)
Rational(20, 9) / 9.8              #=> 0.22675736961451246


# File 'rational.c'

/*
 * call-seq:
 *    rat / numeric     ->  numeric_result
 *    rat.quo(numeric)  ->  numeric_result
 *
 * Performs division.
 *
 * For example:
 *
 *    Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
 *    Rational(900)   / Rational(1)      #=> (900/1)
 *    Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
 *    Rational(9, 8)  / 4                #=> (9/32)
 *    Rational(20, 9) / 9.8              #=> 0.22675736961451246
 */
static VALUE
nurat_div(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
    if (f_zero_p(other))
        rb_raise_zerodiv();
    {
        get_dat1(self);

        return f_muldiv(self,
                dat->num, dat->den,
                other, ONE, '/');
    }
      case T_FLOAT:
    return rb_funcall(f_to_f(self), '/', 1, other);
      case T_RATIONAL:
    if (f_zero_p(other))
        rb_raise_zerodiv();
    {
        get_dat2(self, other);

        if (f_one_p(self))
        return f_rational_new_no_reduce2(CLASS_OF(self),
                         bdat->den, bdat->num);

        return f_muldiv(self,
                adat->num, adat->den,
                bdat->num, bdat->den, '/');
    }
      default:
    return rb_num_coerce_bin(self, other, '/');
    }
}

#quotObject

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_quot(VALUE self, VALUE other)
{
    return f_truncate(f_div(self, other));
}

#quotremObject

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_quotrem(VALUE self, VALUE other)
{
    VALUE val = f_truncate(f_div(self, other));
    return rb_assoc_new(val, f_sub(self, f_mul(other, val)));
}

#rational?Object

:nodoc:



# File 'rational.c'

/* :nodoc: */
static VALUE
nurat_true(VALUE self)
{
    return Qtrue;
}

#rationalizeRational #rationalize(eps) ⇒ Object

Returns a simpler approximation of the value if an optional argument eps is given (rat-|eps| <= result <= rat+|eps|), self otherwise.

For example:

r = Rational(5033165, 16777216)
r.rationalize                    #=> (5033165/16777216)
r.rationalize(Rational('0.01'))  #=> (3/10)
r.rationalize(Rational('0.1'))   #=> (1/3)

Overloads:



# File 'rational.c'

/*
 * call-seq:
 *    rat.rationalize       ->  self
 *    rat.rationalize(eps)  ->  rational
 *
 * Returns a simpler approximation of the value if an optional
 * argument eps is given (rat-|eps| <= result <= rat+|eps|), self
 * otherwise.
 *
 * For example:
 *
 *    r = Rational(5033165, 16777216)
 *    r.rationalize                    #=> (5033165/16777216)
 *    r.rationalize(Rational('0.01'))  #=> (3/10)
 *    r.rationalize(Rational('0.1'))   #=> (1/3)
 */
static VALUE
nurat_rationalize(int argc, VALUE *argv, VALUE self)
{
    VALUE e, a, b, p, q;

    if (argc == 0)
    return self;

    if (f_negative_p(self))
    return f_negate(nurat_rationalize(argc, argv, f_abs(self)));

    rb_scan_args(argc, argv, "01", &e);
    e = f_abs(e);
    a = f_sub(self, e);
    b = f_add(self, e);

    if (f_eqeq_p(a, b))
    return self;

    nurat_rationalize_internal(a, b, &p, &q);
    return f_rational_new2(CLASS_OF(self), p, q);
}

#roundInteger #round(precision = 0) ⇒ Object

Returns the truncated value (toward the nearest integer; 0.5 => 1; -0.5 => -1).

For example:

Rational(3).round      #=> 3
Rational(2, 3).round   #=> 1
Rational(-3, 2).round  #=> -2

       decimal      -  1  2  3 . 4  5  6
                      ^  ^  ^  ^   ^  ^
      precision      -3 -2 -1  0  +1 +2

'%f' % Rational('-123.456').round(+1)  #=> "-123.500000"
'%f' % Rational('-123.456').round(-1)  #=> "-120.000000"

Overloads:



# File 'rational.c'

/*
 * call-seq:
 *    rat.round               ->  integer
 *    rat.round(precision=0)  ->  rational
 *
 * Returns the truncated value (toward the nearest integer;
 * 0.5 => 1; -0.5 => -1).
 *
 * For example:
 *
 *    Rational(3).round      #=> 3
 *    Rational(2, 3).round   #=> 1
 *    Rational(-3, 2).round  #=> -2
 *
 *           decimal      -  1  2  3 . 4  5  6
 *                          ^  ^  ^  ^   ^  ^
 *          precision      -3 -2 -1  0  +1 +2
 *
 *    '%f' % Rational('-123.456').round(+1)  #=> "-123.500000"
 *    '%f' % Rational('-123.456').round(-1)  #=> "-120.000000"
 */
static VALUE
nurat_round_n(int argc, VALUE *argv, VALUE self)
{
    return f_round_common(argc, argv, self, nurat_round);
}

#to_fFloat

Return the value as a float.

For example:

Rational(2).to_f      #=> 2.0
Rational(9, 4).to_f   #=> 2.25
Rational(-3, 4).to_f  #=> -0.75
Rational(20, 3).to_f  #=> 6.666666666666667

Returns:



# File 'rational.c'

/*
 * call-seq:
 *    rat.to_f  ->  float
 *
 * Return the value as a float.
 *
 * For example:
 *
 *    Rational(2).to_f      #=> 2.0
 *    Rational(9, 4).to_f   #=> 2.25
 *    Rational(-3, 4).to_f  #=> -0.75
 *    Rational(20, 3).to_f  #=> 6.666666666666667
 */
static VALUE
nurat_to_f(VALUE self)
{
    get_dat1(self);
    return f_fdiv(dat->num, dat->den);
}

#to_iInteger

Returns the truncated value as an integer.

Equivalent to

rat.truncate.

For example:

Rational(2, 3).to_i   #=> 0
Rational(3).to_i      #=> 3
Rational(300.6).to_i  #=> 300
Rational(98,71).to_i  #=> 1
Rational(-30,2).to_i  #=> -15

Returns:



# File 'rational.c'

/*
 * call-seq:
 *    rat.to_i  ->  integer
 *
 * Returns the truncated value as an integer.
 *
 * Equivalent to
 *    rat.truncate.
 *
 * For example:
 *
 *    Rational(2, 3).to_i   #=> 0
 *    Rational(3).to_i      #=> 3
 *    Rational(300.6).to_i  #=> 300
 *    Rational(98,71).to_i  #=> 1
 *    Rational(-30,2).to_i  #=> -15
 */
static VALUE
nurat_truncate(VALUE self)
{
    get_dat1(self);
    if (f_negative_p(dat->num))
    return f_negate(f_idiv(f_negate(dat->num), dat->den));
    return f_idiv(dat->num, dat->den);
}

#to_rRational

Returns self.

For example:

Rational(2).to_r      #=> (2/1)
Rational(-8, 6).to_r  #=> (-4/3)

Returns:



# File 'rational.c'

/*
 * call-seq:
 *    rat.to_r  ->  self
 *
 * Returns self.
 *
 * For example:
 *
 *    Rational(2).to_r      #=> (2/1)
 *    Rational(-8, 6).to_r  #=> (-4/3)
 */
static VALUE
nurat_to_r(VALUE self)
{
    return self;
}

#to_sString

Returns the value as a string.

For example:

Rational(2).to_s      #=> "2/1"
Rational(-8, 6).to_s  #=> "-4/3"
Rational('0.5').to_s  #=> "1/2"

Returns:



# File 'rational.c'

/*
 * call-seq:
 *    rat.to_s  ->  string
 *
 * Returns the value as a string.
 *
 * For example:
 *
 *    Rational(2).to_s      #=> "2/1"
 *    Rational(-8, 6).to_s  #=> "-4/3"
 *    Rational('0.5').to_s  #=> "1/2"
 */
static VALUE
nurat_to_s(VALUE self)
{
    return f_format(self, f_to_s);
}

#truncateInteger #truncate(precision = 0) ⇒ Object

Returns the truncated value (toward zero).

For example:

Rational(3).truncate      #=> 3
Rational(2, 3).truncate   #=> 0
Rational(-3, 2).truncate  #=> -1

       decimal      -  1  2  3 . 4  5  6
                      ^  ^  ^  ^   ^  ^
      precision      -3 -2 -1  0  +1 +2

'%f' % Rational('-123.456').truncate(+1)  #=>  "-123.400000"
'%f' % Rational('-123.456').truncate(-1)  #=>  "-120.000000"

Overloads:



# File 'rational.c'

/*
 * call-seq:
 *    rat.truncate               ->  integer
 *    rat.truncate(precision=0)  ->  rational
 *
 * Returns the truncated value (toward zero).
 *
 * For example:
 *
 *    Rational(3).truncate      #=> 3
 *    Rational(2, 3).truncate   #=> 0
 *    Rational(-3, 2).truncate  #=> -1
 *
 *           decimal      -  1  2  3 . 4  5  6
 *                          ^  ^  ^  ^   ^  ^
 *          precision      -3 -2 -1  0  +1 +2
 *
 *    '%f' % Rational('-123.456').truncate(+1)  #=>  "-123.400000"
 *    '%f' % Rational('-123.456').truncate(-1)  #=>  "-120.000000"
 */
static VALUE
nurat_truncate_n(int argc, VALUE *argv, VALUE self)
{
    return f_round_common(argc, argv, self, nurat_truncate);
}