Unary Plus—Returns the receiver's value.
static VALUE num_uplus(num) VALUE num; { return num; }
Unary Minus—Returns the receiver's value, negated.
static VALUE num_uminus(num) VALUE num; { VALUE zero; zero = INT2FIX(0); do_coerce(&zero, &num, Qtrue); return rb_funcall(zero, '-', 1, num); }
Returns zero if num equals other, nil
otherwise.
static VALUE num_cmp(x, y) VALUE x, 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
static VALUE num_abs(num) VALUE num; { if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) { return rb_funcall(num, rb_intern("-@"), 0); } return num; }
Returns the smallest Integer
greater than or equal to
num. Class 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(num) VALUE num; { return flo_ceil(rb_Float(num)); }
If aNumeric is the same type as num, returns an array
containing aNumeric and num. Otherwise, returns an array
with both aNumeric 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(x, y) VALUE x, 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); }
Uses /
to perform division, then converts the result to an
integer. Numeric
does not define the /
operator;
this is left to subclasses.
static VALUE num_div(x, y) VALUE x, y; { return num_floor(rb_funcall(x, '/', 1, y)); }
Returns an array containing the quotient and modulus obtained by dividing
num by aNumeric. If q, r = x.divmod(y)
, then
q = floor(float(x)/float(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 | -3 | -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(x, y) VALUE x, y; { return rb_assoc_new(num_div(x, y), rb_funcall(x, '%', 1, y)); }
Returns true
if num and numeric are the same
type and have equal values.
1 == 1.0 #=> true 1.eql?(1.0) #=> false (1.0).eql?(1.0) #=> true
static VALUE num_eql(x, y) VALUE x, y; { if (TYPE(x) != TYPE(y)) return Qfalse; return rb_equal(x, y); }
Returns the largest integer less than or equal to num.
Numeric
implements this by converting anInteger to a
Float
and invoking Float#floor
.
1.floor #=> 1 (-1).floor #=> -1
static VALUE num_floor(num) VALUE num; { return flo_floor(rb_Float(num)); }
Returns true
if num is an Integer
(including Fixnum
and Bignum
).
static VALUE num_int_p(num) VALUE num; { return Qfalse; }
Equivalent to num.divmod(aNumeric).
static VALUE num_modulo(x, y) VALUE x, y; { return rb_funcall(x, '%', 1, y); }
Returns num if num is not zero, nil
otherwise. This behavior is useful when chaining comparisons:
a = %w( z Bb bB bb BB a aA Aa AA A ) b = a.sort {|a,b| (a.downcase <=> b.downcase).nonzero? || a <=> b } b #=> ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"]
static VALUE num_nonzero_p(num) VALUE num; { if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) { return Qnil; } return num; }
Equivalent to Numeric#/
, but overridden in subclasses.
static VALUE num_quo(x, y) VALUE x, y; { return rb_funcall(x, '/', 1, y); }
If num and numeric have different signs, returns
mod-numeric; otherwise, returns mod. In both
cases mod is the value
num.modulo(
numeric)
. The
differences between remainder
and modulo (%
) are
shown in the table under Numeric#divmod
.
static VALUE num_remainder(x, y) VALUE x, y; { VALUE z = rb_funcall(x, '%', 1, y); if ((!rb_equal(z, INT2FIX(0))) && ((RTEST(rb_funcall(x, '<', 1, INT2FIX(0))) && RTEST(rb_funcall(y, '>', 1, INT2FIX(0)))) || (RTEST(rb_funcall(x, '>', 1, INT2FIX(0))) && RTEST(rb_funcall(y, '<', 1, INT2FIX(0)))))) { return rb_funcall(z, '-', 1, y); } return z; }
Rounds num to the nearest integer. Numeric
implements
this by converting itself to a Float
and invoking
Float#round
.
static VALUE num_round(num) VALUE num; { return flo_round(rb_Float(num)); }
Trap attempts to add methods to Numeric
objects. Always raises
a TypeError
static VALUE num_sadded(x, name) VALUE x, name; { ruby_frame = ruby_frame->prev; /* pop frame for "singleton_method_added" */ /* Numerics should be values; singleton_methods should not be added to them */ rb_raise(rb_eTypeError, "can't define singleton method \"%s\" for %s", rb_id2name(rb_to_id(name)), rb_obj_classname(x)); return Qnil; /* not reached */ }
Invokes block with the sequence of numbers starting at
num, incremented by step on each call. The loop finishes
when the value to be passed to the block is greater than limit (if
step is positive) or less than limit (if step is
negative). If all the arguments are integers, the loop operates using an
integer counter. If any of the arguments are floating point numbers, all
are converted to floats, and the loop is executed floor(n + n*epsilon)+
1 times, where n = (limit - num)/step. Otherwise, the loop
starts at num, uses either the <
or
>
operator to compare the counter against limit,
and increments itself using the +
operator.
1.step(10, 2) { |i| print i, " " } Math::E.step(Math::PI, 0.2) { |f| print f, " " }
produces:
1 3 5 7 9 2.71828182845905 2.91828182845905 3.11828182845905
static VALUE num_step(argc, argv, from) int argc; VALUE *argv; VALUE from; { VALUE to, step; if (argc == 1) { to = argv[0]; step = INT2FIX(1); } else { if (argc == 2) { to = argv[0]; step = argv[1]; } else { rb_raise(rb_eArgError, "wrong number of arguments"); } if (rb_equal(step, INT2FIX(0))) { rb_raise(rb_eArgError, "step can't be 0"); } } if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) { long i, end, diff; i = FIX2LONG(from); end = FIX2LONG(to); diff = FIX2LONG(step); if (diff > 0) { while (i <= end) { rb_yield(LONG2FIX(i)); i += diff; } } else { while (i >= end) { rb_yield(LONG2FIX(i)); i += diff; } } } else if (TYPE(from) == T_FLOAT || TYPE(to) == T_FLOAT || TYPE(step) == T_FLOAT) { const double epsilon = DBL_EPSILON; double beg = NUM2DBL(from); double end = NUM2DBL(to); double unit = NUM2DBL(step); double n = (end - beg)/unit; double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon; long i; if (err>0.5) err=0.5; n = floor(n + err) + 1; for (i=0; i<n; i++) { rb_yield(rb_float_new(i*unit+beg)); } } else { VALUE i = from; ID cmp; if (RTEST(rb_funcall(step, '>', 1, INT2FIX(0)))) { cmp = '>'; } else { cmp = '<'; } for (;;) { if (RTEST(rb_funcall(i, cmp, 1, to))) break; rb_yield(i); i = rb_funcall(i, '+', 1, step); } } return from; }
Invokes the child class's to_i
method to convert
num to an integer.
static VALUE num_to_int(num) VALUE num; { return rb_funcall(num, id_to_i, 0, 0); }