Support for the Ruby 2.4 series has ended. See here for reference.
Numeric is the class from which all higher-level numeric classes should inherit.
Numeric allows instantiation of heap-allocated objects. Other core numeric classes such as Integer are implemented as immediates, which means that each Integer is a single immutable object which is always passed by value.
a = 1 puts 1.object_id == a.object_id #=> true
There can only ever be one instance of the integer 1, for example. Ruby ensures this by preventing instantiation and duplication.
Integer.new(1) #=> NoMethodError: undefined method `new' for Integer:Class 1.dup #=> TypeError: can't dup Integer
For this reason, Numeric should be used when defining other numeric classes.
Classes which inherit from Numeric must implement coerce, which returns a two-member Array containing an object that has been coerced into an instance of the new class and self (see coerce).
Inheriting classes should also implement arithmetic operator methods (+, -, * and /) and the <=> operator (see Comparable). These methods may rely on coerce to ensure interoperability with instances of other numeric classes.
class Tally < Numeric def initialize(string) @string = string end def to_s @string end def to_i @string.size end def coerce(other) [self.class.new('|' * other.to_i), self] end def <=>(other) to_i <=> other.to_i end def +(other) self.class.new('|' * (to_i + other.to_i)) end def -(other) self.class.new('|' * (to_i - other.to_i)) end def *(other) self.class.new('|' * (to_i * other.to_i)) end def /(other) self.class.new('|' * (to_i / other.to_i)) end end tally = Tally.new('||') puts tally * 2 #=> "||||" puts tally > 1 #=> true
x.modulo(y) means x-y*(x/y).floor
Equivalent to num.divmod(numeric)[1].
See Numeric#divmod.
static VALUE
num_modulo(VALUE x, VALUE y)
{
VALUE q = num_funcall1(x, id_div, y);
return rb_funcall(x, '-', 1,
rb_funcall(y, '*', 1, q));
}
Unary Plus—Returns the receiver's value.
static VALUE
num_uplus(VALUE num)
{
return num;
}
Unary Minus—Returns the receiver's value, negated.
static VALUE
num_uminus(VALUE num)
{
VALUE zero;
zero = INT2FIX(0);
do_coerce(&zero, &num, TRUE);
return num_funcall1(zero, '-', num);
}
Returns zero if number equals other, otherwise nil is returned if the two values are incomparable.
static VALUE
num_cmp(VALUE x, VALUE y)
{
if (x == y) return INT2FIX(0);
return Qnil;
}
Returns the absolute value of num.
12.abs #=> 12 (-34.56).abs #=> 34.56 -34.56.abs #=> 34.56
Numeric#magnitude is an alias of Numeric#abs.
static VALUE
num_abs(VALUE num)
{
if (negative_int_p(num)) {
return num_funcall0(num, idUMinus);
}
return num;
}
Returns square of self.
static VALUE
numeric_abs2(VALUE self)
{
return f_mul(self, self);
}
Returns 0 if the value is positive, pi otherwise.
static VALUE
numeric_arg(VALUE self)
{
if (f_positive_p(self))
return INT2FIX(0);
return DBL2NUM(M_PI);
}
Returns 0 if the value is positive, pi otherwise.
static VALUE
numeric_arg(VALUE self)
{
if (f_positive_p(self))
return INT2FIX(0);
return DBL2NUM(M_PI);
}
Returns the smallest possible Integer that is greater than or equal to num.
Numeric achieves this by converting itself to a Float then invoking Float#ceil.
1.ceil #=> 1 1.2.ceil #=> 2 (-1.2).ceil #=> -1 (-1.0).ceil #=> -1
static VALUE
num_ceil(int argc, VALUE *argv, VALUE num)
{
return flo_ceil(argc, argv, rb_Float(num));
}
If a numeric is the same type as num, returns an array containing numeric and num. Otherwise, returns an array with both a numeric and num represented as Float objects.
This coercion mechanism is used by Ruby to handle mixed-type numeric operations: it is intended to find a compatible common type between the two operands of the operator.
1.coerce(2.5) #=> [2.5, 1.0] 1.2.coerce(3) #=> [3.0, 1.2] 1.coerce(2) #=> [2, 1]
static VALUE
num_coerce(VALUE x, VALUE y)
{
if (CLASS_OF(x) == CLASS_OF(y))
return rb_assoc_new(y, x);
x = rb_Float(x);
y = rb_Float(y);
return rb_assoc_new(y, x);
}
Returns self.
static VALUE
numeric_conj(VALUE self)
{
return self;
}
Returns self.
static VALUE
numeric_conj(VALUE self)
{
return self;
}
Returns the denominator (always positive).
static VALUE
numeric_denominator(VALUE self)
{
return f_denominator(f_to_r(self));
}
Uses / to perform division, then converts the result to an integer. numeric does not define the / operator; this is left to subclasses.
Equivalent to num.divmod(numeric)[0].
See Numeric#divmod.
static VALUE
num_div(VALUE x, VALUE y)
{
if (rb_equal(INT2FIX(0), y)) rb_num_zerodiv();
return rb_funcall(num_funcall1(x, '/', y), rb_intern("floor"), 0);
}
Returns an array containing the quotient and modulus obtained by dividing num by numeric.
If q, r = * x.divmod(y), then
q = floor(x/y) x = q*y+r
The quotient is rounded toward -infinity, as shown in the following table:
a | b | a.divmod(b) | a/b | a.modulo(b) | a.remainder(b) ------+-----+---------------+---------+-------------+--------------- 13 | 4 | 3, 1 | 3 | 1 | 1 ------+-----+---------------+---------+-------------+--------------- 13 | -4 | -4, -3 | -4 | -3 | 1 ------+-----+---------------+---------+-------------+--------------- -13 | 4 | -4, 3 | -4 | 3 | -1 ------+-----+---------------+---------+-------------+--------------- -13 | -4 | 3, -1 | 3 | -1 | -1 ------+-----+---------------+---------+-------------+--------------- 11.5 | 4 | 2, 3.5 | 2.875 | 3.5 | 3.5 ------+-----+---------------+---------+-------------+--------------- 11.5 | -4 | -3, -0.5 | -2.875 | -0.5 | 3.5 ------+-----+---------------+---------+-------------+--------------- -11.5 | 4 | -3, 0.5 | -2.875 | 0.5 | -3.5 ------+-----+---------------+---------+-------------+--------------- -11.5 | -4 | 2, -3.5 | 2.875 | -3.5 | -3.5
Examples
11.divmod(3) #=> [3, 2] 11.divmod(-3) #=> [-4, -1] 11.divmod(3.5) #=> [3, 0.5] (-11).divmod(3.5) #=> [-4, 3.0] (11.5).divmod(3.5) #=> [3, 1.0]
static VALUE
num_divmod(VALUE x, VALUE y)
{
return rb_assoc_new(num_div(x, y), num_modulo(x, y));
}
Returns true if num and numeric are the same type and have equal values. Contrast this with Numeric#==, which performs type conversions.
1 == 1.0 #=> true 1.eql?(1.0) #=> false (1.0).eql?(1.0) #=> true 68719476736.eql?(68719476736.0) #=> false
static VALUE
num_eql(VALUE x, VALUE y)
{
if (TYPE(x) != TYPE(y)) return Qfalse;
if (RB_TYPE_P(x, T_BIGNUM)) {
return rb_big_eql(x, y);
}
return rb_equal(x, y);
}
Returns float division.
static VALUE
num_fdiv(VALUE x, VALUE y)
{
return rb_funcall(rb_Float(x), '/', 1, y);
}
Return true if num is finite number, oterwise returns false.
static VALUE
num_finite_p(VALUE num)
{
return Qtrue;
}
Returns the largest integer less than or equal to num.
Numeric implements this by converting an Integer to a Float and invoking Float#floor.
1.floor #=> 1 (-1).floor #=> -1
static VALUE
num_floor(int argc, VALUE *argv, VALUE num)
{
return flo_floor(argc, argv, rb_Float(num));
}
Returns the corresponding imaginary number. Not available for complex numbers.
static VALUE
num_imaginary(VALUE num)
{
return rb_complex_new(INT2FIX(0), num);
}
Returns zero.
static VALUE
numeric_imag(VALUE self)
{
return INT2FIX(0);
}
Returns zero.
static VALUE
numeric_imag(VALUE self)
{
return INT2FIX(0);
}
Returns values corresponding to the value of num's magnitude:
finite
nil
-Infinity
-1
Infinity
+1
static VALUE
num_infinite_p(VALUE num)
{
return Qnil;
}
Returns true if num is an Integer.
(1.0).integer? #=> false (1).integer? #=> true
static VALUE
num_int_p(VALUE num)
{
return Qfalse;
}
Returns the absolute value of num.
12.abs #=> 12 (-34.56).abs #=> 34.56 -34.56.abs #=> 34.56
Numeric#magnitude is an alias of Numeric#abs.
static VALUE
num_abs(VALUE num)
{
if (negative_int_p(num)) {
return num_funcall0(num, idUMinus);
}
return num;
}
x.modulo(y) means x-y*(x/y).floor
Equivalent to num.divmod(numeric)[1].
See Numeric#divmod.
static VALUE
num_modulo(VALUE x, VALUE y)
{
VALUE q = num_funcall1(x, id_div, y);
return rb_funcall(x, '-', 1,
rb_funcall(y, '*', 1, q));
}