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:
You can convert certain objects to Rationals with:
Method Rational
.
Examples
Rational(1) Rational(2, 3) Rational(4, -6) 3.to_r 2/3r
You can also create rational objects from floating-point numbers or strings.
Rational(0.3) Rational('0.3') Rational('2/3') 0.3.to_r '0.3'.to_r '2/3'.to_r 0.3.rationalize
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 } 10.times.inject(0) {|t| t + Rational('0.1') }
However, when an expression includes an inexact component (numerical value or operation), it will produce an inexact result.
Rational(10) / 3 Rational(10) / 3.0 Rational(-8) ** Rational(1, 3)Public Class Methods Source
def self.json_create(object) Rational(object['n'], object['d']) end
See as_json
.
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) Rational(900) * Rational(1) Rational(-2, 9) * Rational(-9, 2) Rational(9, 8) * 4 Rational(20, 9) * 9.8Source
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) Rational(10) ** -2 Rational(10) ** -2.0 Rational(-4) ** Rational(1, 2) Rational(1, 2) ** 0 Rational(1, 2) ** 0.0Source
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) Rational(900) + Rational(1) Rational(-2, 9) + Rational(-9, 2) Rational(9, 8) + 4 Rational(20, 9) + 9.8Source
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) Rational(900) - Rational(1) Rational(-2, 9) - Rational(-9, 2) Rational(9, 8) - 4 Rational(20, 9) - 9.8Source
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
.
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) Rational(900) / Rational(1) Rational(-2, 9) / Rational(-9, 2) Rational(9, 8) / 4 Rational(20, 9) / 9.8Source
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) Rational(5) <=> 5 Rational(2, 3) <=> Rational(1, 3) Rational(1, 3) <=> 1 Rational(1, 3) <=> 0.3 Rational(1, 3) <=> "0.3"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) Rational(5) == 5 Rational(0) == 0.0 Rational('1/3') == 0.33 Rational('1/2') == '1/2'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/2r).absSource
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
Method JSON.create
deserializes such a hash, returning a Rational object:
Rational.json_create(x)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 Rational(2, 3).ceil Rational(-3, 2).ceil Rational('-123.456').ceil(+1).to_f Rational('-123.456').ceil(-1)Source
static VALUE nurat_denominator(VALUE self) { get_dat1(self); return dat->den; }
Returns the denominator (always positive).
Rational(7).denominator Rational(7, 1).denominator Rational(9, -4).denominator Rational(-2, -10).denominatorSource
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) Rational(2, 3).fdiv(0.5) Rational(2).fdiv(3)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 Rational(2, 3).floor Rational(-3, 2).floor Rational('-123.456').floor(+1).to_f Rational('-123.456').floor(-1)Source
static VALUE nurat_hash(VALUE self) { return ST2FIX(rb_rational_hash(self)); }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 Rational(-8, 6).inspect Rational('1/2').inspect
Returns the absolute value of rat
.
(1/2r).abs (-1/2r).absSource
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.
static VALUE nurat_numerator(VALUE self) { get_dat1(self); return dat->num; }
Returns the numerator.
Rational(7).numerator Rational(7, 1).numerator Rational(9, -4).numerator Rational(-2, -10).numeratorSource
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.
Performs division.
Rational(2, 3) / Rational(2, 3) Rational(900) / Rational(1) Rational(-2, 9) / Rational(-9, 2) Rational(9, 8) / 4 Rational(20, 9) / 9.8Source
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 r.rationalize(Rational('0.01')) r.rationalize(Rational('0.1'))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 Rational(2, 3).round Rational(-3, 2).round Rational('-123.456').round(+1).to_f Rational('-123.456').round(-1)
The optional half
keyword argument is available similar to Float#round
.
Rational(25, 100).round(1, half: :up) Rational(25, 100).round(1, half: :down) Rational(25, 100).round(1, half: :even) Rational(35, 100).round(1, half: :up) Rational(35, 100).round(1, half: :down) Rational(35, 100).round(1, half: :even) Rational(-25, 100).round(1, half: :up) Rational(-25, 100).round(1, half: :down) Rational(-25, 100).round(1, half: :even)Source
static VALUE nurat_to_f(VALUE self) { return DBL2NUM(nurat_to_double(self)); }
Returns the value as a Float
.
Rational(2).to_f Rational(9, 4).to_f Rational(-3, 4).to_f Rational(20, 3).to_fSource
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 Rational(3).to_i Rational(300.6).to_i Rational(98, 71).to_i Rational(-31, 2).to_iSource
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}Source
static VALUE nurat_to_r(VALUE self) { return self; }
Returns self.
Rational(2).to_r Rational(-8, 6).to_rSource
static VALUE nurat_to_s(VALUE self) { return f_format(self, f_to_s); }
Returns the value as a string.
Rational(2).to_s Rational(-8, 6).to_s Rational('1/2').to_sSource
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 Rational(2, 3).truncate Rational(-3, 2).truncate Rational('-123.456').truncate(+1).to_f Rational('-123.456').truncate(-1)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.3