Class: Rational
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, to_r or rationalize 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)
0.3.rationalize #=> (3/10)
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
-
#*(numeric) ⇒ Numeric
Performs multiplication.
-
#**(numeric) ⇒ Numeric
Performs exponentiation.
-
#+(numeric) ⇒ Numeric
Performs addition.
-
#-(numeric) ⇒ Numeric
Performs subtraction.
-
#/ ⇒ Object
Performs division.
-
#// ⇒ Object
:nodoc:.
-
#<=>(numeric) ⇒ -1, ...
Performs comparison and returns -1, 0, or +1.
-
#==(object) ⇒ Boolean
Returns true if rat equals object numerically.
-
#ceil ⇒ Object
Returns the truncated value (toward positive infinity).
-
#coerce ⇒ Object
:nodoc:.
-
#denominator ⇒ Integer
Returns the denominator (always positive).
-
#exact? ⇒ Object
:nodoc:.
-
#fdiv(numeric) ⇒ Float
Performs division and returns the value as a float.
-
#floor ⇒ Object
Returns the truncated value (toward negative infinity).
-
#hash ⇒ Object
:nodoc:.
-
#inspect ⇒ String
Returns the value as a string for inspection.
-
#marshal_dump ⇒ Object
:nodoc:.
-
#marshal_load ⇒ Object
:nodoc:.
-
#numerator ⇒ Integer
Returns the numerator.
-
#quo ⇒ Object
Performs division.
-
#quot ⇒ Object
:nodoc:.
-
#quotrem ⇒ Object
:nodoc:.
-
#rational? ⇒ Object
:nodoc:.
-
#rationalize ⇒ Object
Returns a simpler approximation of the value if an optional argument eps is given (rat-|eps| <= result <= rat+|eps|), self otherwise.
-
#round ⇒ Object
Returns the truncated value (toward the nearest integer; 0.5 => 1; -0.5 => -1).
-
#to_f ⇒ Float
Return the value as a float.
-
#to_i ⇒ Integer
Returns the truncated value as an integer.
-
#to_r ⇒ Rational
Returns self.
-
#to_s ⇒ String
Returns the value as a string.
-
#truncate ⇒ Object
Returns the truncated value (toward zero).
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
Instance Method Details
#*(numeric) ⇒ Numeric
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'
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, '*');
}
|
#**(numeric) ⇒ Numeric
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'
static VALUE
nurat_expt(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 */
}
|
#+(numeric) ⇒ Numeric
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'
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, '+');
}
|
#-(numeric) ⇒ Numeric
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'
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, '-');
}
|
#/(numeric) ⇒ Numeric #quo(numeric) ⇒ Numeric
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'
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, '/');
}
|
#// ⇒ Object
:nodoc:
|
# File 'rational.c'
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
|
# File 'rational.c'
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));
}
|
#==(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
|
# File 'rational.c'
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;
}
|
#ceil ⇒ Integer #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"
|
# File 'rational.c'
static VALUE
nurat_ceil_n(int argc, VALUE *argv, VALUE self)
{
return f_round_common(argc, argv, self, nurat_ceil);
}
|
#coerce ⇒ Object
:nodoc:
|
# File 'rational.c'
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);
else
return rb_assoc_new(other, rb_Complex(self, INT2FIX(0)));
}
|
#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
|
# File 'rational.c'
static VALUE
nurat_denominator(VALUE self)
{
get_dat1(self);
return dat->den;
}
|
#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
|
# File 'rational.c'
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));
}
|
#floor ⇒ Integer #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"
|
# File 'rational.c'
static VALUE
nurat_floor_n(int argc, VALUE *argv, VALUE self)
{
return f_round_common(argc, argv, self, nurat_floor);
}
|
#hash ⇒ Object
:nodoc:
|
# File 'rational.c'
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);
}
|
#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)"
|
# File 'rational.c'
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_dump ⇒ Object
:nodoc:
|
# File 'rational.c'
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_load ⇒ Object
:nodoc:
|
# File 'rational.c'
static VALUE
nurat_marshal_load(VALUE self, VALUE a)
{
get_dat1(self);
Check_Type(a, T_ARRAY);
if (RARRAY_LEN(a) != 2)
rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
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;
}
|
#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
|
# File 'rational.c'
static VALUE
nurat_numerator(VALUE self)
{
get_dat1(self);
return dat->num;
}
|
#/(numeric) ⇒ Numeric #quo(numeric) ⇒ Numeric
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'
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, '/');
}
|
#quot ⇒ Object
:nodoc:
|
# File 'rational.c'
static VALUE
nurat_quot(VALUE self, VALUE other)
{
return f_truncate(f_div(self, other));
}
|
#quotrem ⇒ Object
:nodoc:
|
# File 'rational.c'
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'
static VALUE
nurat_true(VALUE self)
{
return Qtrue;
}
|
#rationalize ⇒ Rational #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)
|
# File 'rational.c'
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);
}
|
#round ⇒ Integer #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"
|
# File 'rational.c'
static VALUE
nurat_round_n(int argc, VALUE *argv, VALUE self)
{
return f_round_common(argc, argv, self, nurat_round);
}
|
#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
|
# File 'rational.c'
static VALUE
nurat_to_f(VALUE self)
{
get_dat1(self);
return f_fdiv(dat->num, dat->den);
}
|
#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
|
# File 'rational.c'
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_r ⇒ Rational
Returns self.
For example:
Rational(2).to_r #=> (2/1)
Rational(-8, 6).to_r #=> (-4/3)
|
# File 'rational.c'
static VALUE
nurat_to_r(VALUE self)
{
return self;
}
|
#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"
|
# File 'rational.c'
static VALUE
nurat_to_s(VALUE self)
{
return f_format(self, f_to_s);
}
|
#truncate ⇒ Integer #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"
|
# File 'rational.c'
static VALUE
nurat_truncate_n(int argc, VALUE *argv, VALUE self)
{
return f_round_common(argc, argv, self, nurat_truncate);
}
|