# class Rational

A rational number can be represented as a pair of integer numbers: a/b (b>0), where a is the numerator and b is the denominator. `Integer` a equals rational a/1 mathematically.

You can create a Rational object explicitly with:

- A rational literal.

You can convert certain objects to Rationals with:

- Method `Rational`.

Examples

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

You can also create rational objects 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)
    0.3.rationalize  #=> (3/10)

A rational object is an exact number, which helps you to write programs 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 includes an inexact component (numerical value or operation), it 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)

### Public Class Methods

json_create (object)
Source

    # File ext/json/lib/json/add/rational.rb, line 9
    def self.json_create(object)
      Rational(object['n'], object['d'])
    end

See `as_json`.

### Public Instance Methods

rat * numeric → numeric
Source

    VALUE
    rb_rational_mul(VALUE self, VALUE other)
    {
        if (RB_INTEGER_TYPE_P(other)) {
            {
                get_dat1(self);

                return f_muldiv(self,
                                dat->num, dat->den,
                                other, ONE, '*');
            }
        }
        else if (RB_FLOAT_TYPE_P(other)) {
            return DBL2NUM(nurat_to_double(self) * RFLOAT_VALUE(other));
        }
        else if (RB_TYPE_P(other, T_RATIONAL)) {
            {
                get_dat2(self, other);

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

Performs multiplication.

    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

rat ** numeric → numeric
Source

    VALUE
    rb_rational_pow(VALUE self, VALUE other)
    {
        if (k_numeric_p(other) && 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 */
        }

        /* Deal with special cases of 0**n and 1**n */
        if (k_numeric_p(other) && k_exact_p(other)) {
            get_dat1(self);
            if (f_one_p(dat->den)) {
                if (f_one_p(dat->num)) {
                    return f_rational_new_bang1(CLASS_OF(self), ONE);
                }
                else if (f_minus_one_p(dat->num) && RB_INTEGER_TYPE_P(other)) {
                    return f_rational_new_bang1(CLASS_OF(self), INT2FIX(rb_int_odd_p(other) ? -1 : 1));
                }
                else if (INT_ZERO_P(dat->num)) {
                    if (rb_num_negative_p(other)) {
                        rb_num_zerodiv();
                    }
                    else {
                        return f_rational_new_bang1(CLASS_OF(self), ZERO);
                    }
                }
            }
        }

        /* General case */
        if (FIXNUM_P(other)) {
            {
                VALUE num, den;

                get_dat1(self);

                if (INT_POSITIVE_P(other)) {
                    num = rb_int_pow(dat->num, other);
                    den = rb_int_pow(dat->den, other);
                }
                else if (INT_NEGATIVE_P(other)) {
                    num = rb_int_pow(dat->den, rb_int_uminus(other));
                    den = rb_int_pow(dat->num, rb_int_uminus(other));
                }
                else {
                    num = ONE;
                    den = ONE;
                }
                if (RB_FLOAT_TYPE_P(num)) { /* infinity due to overflow */
                    if (RB_FLOAT_TYPE_P(den))
                        return DBL2NUM(nan(""));
                    return num;
                }
                if (RB_FLOAT_TYPE_P(den)) { /* infinity due to overflow */
                    num = ZERO;
                    den = ONE;
                }
                return f_rational_new2(CLASS_OF(self), num, den);
            }
        }
        else if (RB_BIGNUM_TYPE_P(other)) {
            rb_raise(rb_eArgError, "exponent is too large");
        }
        else if (RB_FLOAT_TYPE_P(other) || RB_TYPE_P(other, T_RATIONAL)) {
            return rb_float_pow(nurat_to_f(self), other);
        }
        else {
            return rb_num_coerce_bin(self, other, idPow);
        }
    }

Performs exponentiation.

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

rat + numeric → numeric
Source

    VALUE
    rb_rational_plus(VALUE self, VALUE other)
    {
        if (RB_INTEGER_TYPE_P(other)) {
            {
                get_dat1(self);

                return f_rational_new_no_reduce2(CLASS_OF(self),
                                                 rb_int_plus(dat->num, rb_int_mul(other, dat->den)),
                                                 dat->den);
            }
        }
        else if (RB_FLOAT_TYPE_P(other)) {
            return DBL2NUM(nurat_to_double(self) + RFLOAT_VALUE(other));
        }
        else if (RB_TYPE_P(other, T_RATIONAL)) {
            {
                get_dat2(self, other);

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

Performs addition.

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

rat - numeric → numeric
Source

    VALUE
    rb_rational_minus(VALUE self, VALUE other)
    {
        if (RB_INTEGER_TYPE_P(other)) {
            {
                get_dat1(self);

                return f_rational_new_no_reduce2(CLASS_OF(self),
                                                 rb_int_minus(dat->num, rb_int_mul(other, dat->den)),
                                                 dat->den);
            }
        }
        else if (RB_FLOAT_TYPE_P(other)) {
            return DBL2NUM(nurat_to_double(self) - RFLOAT_VALUE(other));
        }
        else if (RB_TYPE_P(other, T_RATIONAL)) {
            {
                get_dat2(self, other);

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

Performs subtraction.

    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

-rat → rational
Source

    VALUE
    rb_rational_uminus(VALUE self)
    {
        const int unused = (RUBY_ASSERT(RB_TYPE_P(self, T_RATIONAL)), 0);
        get_dat1(self);
        (void)unused;
        return f_rational_new2(CLASS_OF(self), rb_int_uminus(dat->num), dat->den);
    }

Negates `rat`.

rat / numeric → numeric
Source

    VALUE
    rb_rational_div(VALUE self, VALUE other)
    {
        if (RB_INTEGER_TYPE_P(other)) {
            if (f_zero_p(other))
                rb_num_zerodiv();
            {
                get_dat1(self);

                return f_muldiv(self,
                                dat->num, dat->den,
                                other, ONE, '/');
            }
        }
        else if (RB_FLOAT_TYPE_P(other)) {
            VALUE v = nurat_to_f(self);
            return rb_flo_div_flo(v, other);
        }
        else if (RB_TYPE_P(other, T_RATIONAL)) {
            if (f_zero_p(other))
                rb_num_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, '/');
            }
        }
        else {
            return rb_num_coerce_bin(self, other, '/');
        }
    }

Performs division.

    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

Also aliased as: quo
rational <=> numeric → -1, 0, +1, or nil
Source

    VALUE
    rb_rational_cmp(VALUE self, VALUE other)
    {
        switch (TYPE(other)) {
          case T_FIXNUM:
          case T_BIGNUM:
            {
                get_dat1(self);

                if (dat->den == LONG2FIX(1))
                    return rb_int_cmp(dat->num, other); /* c14n */
                other = f_rational_new_bang1(CLASS_OF(self), other);
                /* FALLTHROUGH */
            }

          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 = rb_int_mul(adat->num, bdat->den);
                    num2 = rb_int_mul(bdat->num, adat->den);
                }
                return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
            }

          case T_FLOAT:
            return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other));

          default:
            return rb_num_coerce_cmp(self, other, idCmp);
        }
    }

Returns -1, 0, or +1 depending on whether `rational` is less than, equal to, or greater than `numeric`.

`nil` is returned if the two values are incomparable.

    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

    Rational(1, 3) <=> "0.3"           #=> nil

rat == object → true or false
Source

    static VALUE
    nurat_eqeq_p(VALUE self, VALUE other)
    {
        if (RB_INTEGER_TYPE_P(other)) {
            get_dat1(self);

            if (RB_INTEGER_TYPE_P(dat->num) && RB_INTEGER_TYPE_P(dat->den)) {
                if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
                    return Qtrue;

                if (!FIXNUM_P(dat->den))
                    return Qfalse;
                if (FIX2LONG(dat->den) != 1)
                    return Qfalse;
                return rb_int_equal(dat->num, other);
            }
            else {
                const double d = nurat_to_double(self);
                return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
            }
        }
        else if (RB_FLOAT_TYPE_P(other)) {
            const double d = nurat_to_double(self);
            return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, RFLOAT_VALUE(other))));
        }
        else if (RB_TYPE_P(other, T_RATIONAL)) {
            {
                get_dat2(self, other);

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

                return RBOOL(rb_int_equal(adat->num, bdat->num) &&
                                  rb_int_equal(adat->den, bdat->den));
            }
        }
        else {
            return rb_equal(other, self);
        }
    }

Returns `true` if `rat` equals `object` numerically.

    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

abs → rational
Source

    VALUE
    rb_rational_abs(VALUE self)
    {
        get_dat1(self);
        if (INT_NEGATIVE_P(dat->num)) {
            VALUE num = rb_int_abs(dat->num);
            return nurat_s_canonicalize_internal_no_reduce(CLASS_OF(self), num, dat->den);
        }
        return self;
    }

Returns the absolute value of `rat`.

    (1/2r).abs    #=> (1/2)
    (-1/2r).abs   #=> (1/2)

Also aliased as: magnitude
as_json (*)
Source

    # File ext/json/lib/json/add/rational.rb, line 29
    def as_json(*)
      {
        JSON.create_id => self.class.name,
        'n'            => numerator,
        'd'            => denominator,
      }
    end

Methods `Rational#as_json` and `Rational.json_create` may be used to serialize and deserialize a Rational object; see `Marshal`.

Method `Rational#as_json` serializes `self`, returning a 2-element hash representing `self`:

    require 'json/add/rational'
    x = Rational(2, 3).as_json
    # => {"json_class"=>"Rational", "n"=>2, "d"=>3}

Method `JSON.create` deserializes such a hash, returning a Rational object:

    Rational.json_create(x)
    # => (2/3)

ceil([ndigits]) → integer or rational
Source

    static VALUE
    nurat_ceil_n(int argc, VALUE *argv, VALUE self)
    {
        return f_round_common(argc, argv, self, nurat_ceil);
    }

Returns the smallest number greater than or equal to `rat` with a precision of `ndigits` decimal digits (default: 0).

When the precision is negative, the returned value is an integer with at least `ndigits.abs` trailing zeros.

Returns a rational when `ndigits` is positive, otherwise returns an integer.

    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

    Rational('-123.456').ceil(+1).to_f  #=> -123.4
    Rational('-123.456').ceil(-1)       #=> -120

denominator → integer
Source

    static VALUE
    nurat_denominator(VALUE self)
    {
        get_dat1(self);
        return dat->den;
    }

Returns the denominator (always positive).

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

fdiv(numeric) → float
Source

    static VALUE
    nurat_fdiv(VALUE self, VALUE other)
    {
        VALUE div;
        if (f_zero_p(other))
            return rb_rational_div(self, rb_float_new(0.0));
        if (FIXNUM_P(other) && other == LONG2FIX(1))
            return nurat_to_f(self);
        div = rb_rational_div(self, other);
        if (RB_TYPE_P(div, T_RATIONAL))
            return nurat_to_f(div);
        if (RB_FLOAT_TYPE_P(div))
            return div;
        return rb_funcall(div, idTo_f, 0);
    }

Performs division and returns the value as a `Float`.

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

floor([ndigits]) → integer or rational
Source

    static VALUE
    nurat_floor_n(int argc, VALUE *argv, VALUE self)
    {
        return f_round_common(argc, argv, self, nurat_floor);
    }

Returns the largest number less than or equal to `rat` with a precision of `ndigits` decimal digits (default: 0).

When the precision is negative, the returned value is an integer with at least `ndigits.abs` trailing zeros.

Returns a rational when `ndigits` is positive, otherwise returns an integer.

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

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

    Rational('-123.456').floor(+1).to_f  #=> -123.5
    Rational('-123.456').floor(-1)       #=> -130

hash ()
Source

    static VALUE
    nurat_hash(VALUE self)
    {
        return ST2FIX(rb_rational_hash(self));
    }

inspect → string
Source

    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;
    }

Returns the value as a string for inspection.

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

magnitude → rational

Returns the absolute value of `rat`.

    (1/2r).abs    #=> (1/2)
    (-1/2r).abs   #=> (1/2)

Alias for: abs
negative? → true or false
Source

    static VALUE
    nurat_negative_p(VALUE self)
    {
        get_dat1(self);
        return RBOOL(INT_NEGATIVE_P(dat->num));
    }

Returns `true` if `rat` is less than 0.

numerator → integer
Source

    static VALUE
    nurat_numerator(VALUE self)
    {
        get_dat1(self);
        return dat->num;
    }

Returns the numerator.

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

positive? → true or false
Source

    static VALUE
    nurat_positive_p(VALUE self)
    {
        get_dat1(self);
        return RBOOL(INT_POSITIVE_P(dat->num));
    }

Returns `true` if `rat` is greater than 0.

quo(numeric) → numeric

Performs division.

    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

Alias for: /
rationalize → self
rationalize(eps) → rational
Source

    static VALUE
    nurat_rationalize(int argc, VALUE *argv, VALUE self)
    {
        VALUE e, a, b, p, q;
        VALUE rat = self;
        get_dat1(self);

        if (rb_check_arity(argc, 0, 1) == 0)
            return self;

        e = f_abs(argv[0]);

        if (INT_NEGATIVE_P(dat->num)) {
            rat = f_rational_new2(RBASIC_CLASS(self), rb_int_uminus(dat->num), dat->den);
        }

        a = FIXNUM_ZERO_P(e) ? rat : rb_rational_minus(rat, e);
        b = FIXNUM_ZERO_P(e) ? rat : rb_rational_plus(rat, e);

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

        nurat_rationalize_internal(a, b, &p, &q);
        if (rat != self) {
            RATIONAL_SET_NUM(rat, rb_int_uminus(p));
            RATIONAL_SET_DEN(rat, q);
            return rat;
        }
        return f_rational_new2(CLASS_OF(self), p, q);
    }

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

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

round([ndigits] [, half: mode]) → integer or rational
Source

    static VALUE
    nurat_round_n(int argc, VALUE *argv, VALUE self)
    {
        VALUE opt;
        enum ruby_num_rounding_mode mode = (
            argc = rb_scan_args(argc, argv, "*:", NULL, &opt),
            rb_num_get_rounding_option(opt));
        VALUE (*round_func)(VALUE) = ROUND_FUNC(mode, nurat_round);
        return f_round_common(argc, argv, self, round_func);
    }

Returns `rat` rounded to the nearest value with a precision of `ndigits` decimal digits (default: 0).

When the precision is negative, the returned value is an integer with at least `ndigits.abs` trailing zeros.

Returns a rational when `ndigits` is positive, otherwise returns an integer.

    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

    Rational('-123.456').round(+1).to_f  #=> -123.5
    Rational('-123.456').round(-1)       #=> -120

The optional `half` keyword argument is available similar to `Float#round`.

    Rational(25, 100).round(1, half: :up)    #=> (3/10)
    Rational(25, 100).round(1, half: :down)  #=> (1/5)
    Rational(25, 100).round(1, half: :even)  #=> (1/5)
    Rational(35, 100).round(1, half: :up)    #=> (2/5)
    Rational(35, 100).round(1, half: :down)  #=> (3/10)
    Rational(35, 100).round(1, half: :even)  #=> (2/5)
    Rational(-25, 100).round(1, half: :up)   #=> (-3/10)
    Rational(-25, 100).round(1, half: :down) #=> (-1/5)
    Rational(-25, 100).round(1, half: :even) #=> (-1/5)

to_f → float
Source

    static VALUE
    nurat_to_f(VALUE self)
    {
        return DBL2NUM(nurat_to_double(self));
    }

Returns the value as a `Float`.

    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

to_i → integer
Source

    static VALUE
    nurat_truncate(VALUE self)
    {
        get_dat1(self);
        if (INT_NEGATIVE_P(dat->num))
            return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
        return rb_int_idiv(dat->num, dat->den);
    }

Returns the truncated value as an integer.

Equivalent to `Rational#truncate`.

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

to_json (*args)
Source

    # File ext/json/lib/json/add/rational.rb, line 46
    def to_json(*args)
      as_json.to_json(*args)
    end

Returns a `JSON` string representing `self`:

    require 'json/add/rational'
    puts Rational(2, 3).to_json

Output:

    {"json_class":"Rational","n":2,"d":3}

to_r → self
Source

    static VALUE
    nurat_to_r(VALUE self)
    {
        return self;
    }

Returns self.

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

to_s → string
Source

    static VALUE
    nurat_to_s(VALUE self)
    {
        return f_format(self, f_to_s);
    }

Returns the value as a string.

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

truncate([ndigits]) → integer or rational
Source

    static VALUE
    nurat_truncate_n(int argc, VALUE *argv, VALUE self)
    {
        return f_round_common(argc, argv, self, nurat_truncate);
    }

Returns `rat` truncated (toward zero) to a precision of `ndigits` decimal digits (default: 0).

When the precision is negative, the returned value is an integer with at least `ndigits.abs` trailing zeros.

Returns a rational when `ndigits` is positive, otherwise returns an integer.

    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

    Rational('-123.456').truncate(+1).to_f  #=> -123.4
    Rational('-123.456').truncate(-1)       #=> -120