Class: Numeric
Overview
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
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. If duplication is attempted, the same instance is returned.
Integer.new(1) #=> NoMethodError: undefined method `new' for Integer:Class
1.dup #=> 1
1.object_id == 1.dup.object_id #=> true
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
Instance Method Summary collapse
-
#modulo(numeric) ⇒ Object
x.modulo(y)
meansx-y*(x/y).floor
. -
#+ ⇒ Numeric
Unary Plus—Returns the receiver.
-
#- ⇒ Numeric
Unary Minus—Returns the receiver, negated.
-
#<=>(other) ⇒ 0?
Returns zero if
number
equalsother
, otherwise returnsnil
. -
#abs ⇒ Object
Returns the absolute value of
num
. -
#abs2 ⇒ Object
Returns square of self.
-
#angle ⇒ Object
Returns 0 if the value is positive, pi otherwise.
-
#arg ⇒ Object
Returns 0 if the value is positive, pi otherwise.
-
#ceil([ndigits]) ⇒ Integer, Float
Returns the smallest number greater than or equal to
num
with a precision ofndigits
decimal digits (default: 0). -
#clone(freeze: true) ⇒ Numeric
Returns the receiver.
-
#coerce(numeric) ⇒ Array
If
numeric
is the same type asnum
, returns an array[numeric, num]
. -
#conj ⇒ Object
Returns self.
-
#conjugate ⇒ Object
Returns self.
-
#denominator ⇒ Integer
Returns the denominator (always positive).
-
#div(numeric) ⇒ Integer
Uses
/
to perform division, then converts the result to an integer. -
#divmod(numeric) ⇒ Array
Returns an array containing the quotient and modulus obtained by dividing
num
bynumeric
. -
#dup ⇒ Numeric
Returns the receiver.
-
#eql?(numeric) ⇒ Boolean
Returns
true
ifnum
andnumeric
are the same type and have equal values. -
#fdiv(numeric) ⇒ Float
Returns float division.
-
#finite? ⇒ Boolean
Returns
true
ifnum
is a finite number, otherwise returnsfalse
. -
#floor([ndigits]) ⇒ Integer, Float
Returns the largest number less than or equal to
num
with a precision ofndigits
decimal digits (default: 0). -
#i ⇒ Complex(0]
Returns the corresponding imaginary number.
-
#imag ⇒ Object
Returns zero.
-
#imaginary ⇒ Object
Returns zero.
-
#infinite? ⇒ -1, ...
Returns
nil
, -1, or 1 depending on whether the value is finite,-Infinity
, or+Infinity
. -
#integer? ⇒ Boolean
Returns
true
ifnum
is an Integer. -
#magnitude ⇒ Object
Returns the absolute value of
num
. -
#modulo(numeric) ⇒ Object
x.modulo(y)
meansx-y*(x/y).floor
. -
#negative? ⇒ Boolean
Returns
true
ifnum
is less than 0. -
#nonzero? ⇒ self?
Returns
self
ifnum
is not zero,nil
otherwise. -
#numerator ⇒ Integer
Returns the numerator.
-
#phase ⇒ Object
Returns 0 if the value is positive, pi otherwise.
-
#polar ⇒ Array
Returns an array; [num.abs, num.arg].
-
#positive? ⇒ Boolean
Returns
true
ifnum
is greater than 0. -
#quo(y) ⇒ Object
Returns the most exact division (rational for integers, float for floats).
-
#real ⇒ self
Returns self.
-
#real? ⇒ Boolean
Returns
true
ifnum
is a real number (i.e. not Complex). -
#rect ⇒ Object
Returns an array; [num, 0].
-
#rectangular ⇒ Object
Returns an array; [num, 0].
-
#remainder(numeric) ⇒ Object
x.remainder(y)
meansx-y*(x/y).truncate
. -
#round([ndigits]) ⇒ Integer, Float
Returns
num
rounded to the nearest value with a precision ofndigits
decimal digits (default: 0). -
#singleton_method_added(name) ⇒ Object
:nodoc:.
-
#step(*args) ⇒ Object
Invokes the given block with the sequence of numbers starting at
num
, incremented bystep
(defaulted to1
) on each call. -
#to_c ⇒ Object
Returns the value as a complex.
-
#to_int ⇒ Integer
Invokes the child class’s
to_i
method to convertnum
to an integer. -
#truncate([ndigits]) ⇒ Integer, Float
Returns
num
truncated (toward zero) to a precision ofndigits
decimal digits (default: 0). -
#zero? ⇒ Boolean
Returns
true
ifnum
has a zero value.
Methods included from Comparable
#<, #<=, #==, #>, #>=, #between?, #clamp
Instance Method Details
#modulo(numeric) ⇒ Object
x.modulo(y)
means x-y*(x/y).floor
.
Equivalent to num.divmod(numeric)[1]
.
See Numeric#divmod.
618 619 620 621 622 623 624 |
# File 'numeric.c', line 618
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));
}
|
#+ ⇒ Numeric
Unary Plus—Returns the receiver.
534 535 536 537 538 |
# File 'numeric.c', line 534
static VALUE
num_uplus(VALUE num)
{
return num;
}
|
#- ⇒ Numeric
Unary Minus—Returns the receiver, negated.
564 565 566 567 568 569 570 571 572 573 |
# File 'numeric.c', line 564
static VALUE
num_uminus(VALUE num)
{
VALUE zero;
zero = INT2FIX(0);
do_coerce(&zero, &num, TRUE);
return num_funcall1(zero, '-', num);
}
|
#<=>(other) ⇒ 0?
Returns zero if number
equals other
, otherwise returns nil
.
1352 1353 1354 1355 1356 1357 |
# File 'numeric.c', line 1352
static VALUE
num_cmp(VALUE x, VALUE y)
{
if (x == y) return INT2FIX(0);
return Qnil;
}
|
#abs ⇒ Numeric #magnitude ⇒ Numeric
Returns the absolute value of num
.
12.abs #=> 12
(-34.56).abs #=> 34.56
-34.56.abs #=> 34.56
Numeric#magnitude is an alias for Numeric#abs.
742 743 744 745 746 747 748 749 |
# File 'numeric.c', line 742
static VALUE
num_abs(VALUE num)
{
if (rb_num_negative_int_p(num)) {
return num_funcall0(num, idUMinus);
}
return num;
}
|
#abs2 ⇒ Object
Returns square of self.
2177 2178 2179 2180 2181 |
# File 'complex.c', line 2177
static VALUE
numeric_abs2(VALUE self)
{
return f_mul(self, self);
}
|
#arg ⇒ 0, Float #angle ⇒ 0, Float #phase ⇒ 0, Float
Returns 0 if the value is positive, pi otherwise.
2191 2192 2193 2194 2195 2196 2197 |
# File 'complex.c', line 2191
static VALUE
numeric_arg(VALUE self)
{
if (f_positive_p(self))
return INT2FIX(0);
return DBL2NUM(M_PI);
}
|
#arg ⇒ 0, Float #angle ⇒ 0, Float #phase ⇒ 0, Float
Returns 0 if the value is positive, pi otherwise.
2191 2192 2193 2194 2195 2196 2197 |
# File 'complex.c', line 2191
static VALUE
numeric_arg(VALUE self)
{
if (f_positive_p(self))
return INT2FIX(0);
return DBL2NUM(M_PI);
}
|
#ceil([ndigits]) ⇒ Integer, Float
Returns the smallest number greater than or equal to num
with a precision of ndigits
decimal digits (default: 0).
Numeric implements this by converting its value to a Float and invoking Float#ceil.
2454 2455 2456 2457 2458 |
# File 'numeric.c', line 2454
static VALUE
num_ceil(int argc, VALUE *argv, VALUE num)
{
return flo_ceil(argc, argv, rb_Float(num));
}
|
#clone(freeze: true) ⇒ Numeric
Returns the receiver. freeze
cannot be false
.
502 503 504 505 506 |
# File 'numeric.c', line 502
static VALUE
num_clone(int argc, VALUE *argv, VALUE x)
{
return rb_immutable_obj_clone(argc, argv, x);
}
|
#coerce(numeric) ⇒ Array
If numeric
is the same type as num
, returns an array [numeric, num]
. Otherwise, returns an array with both 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]
399 400 401 402 403 404 405 406 407 |
# File 'numeric.c', line 399
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);
}
|
#conj ⇒ self #conjugate ⇒ self
Returns self.
2251 2252 2253 2254 2255 |
# File 'complex.c', line 2251
static VALUE
numeric_conj(VALUE self)
{
return self;
}
|
#conj ⇒ self #conjugate ⇒ self
Returns self.
2251 2252 2253 2254 2255 |
# File 'complex.c', line 2251
static VALUE
numeric_conj(VALUE self)
{
return self;
}
|
#denominator ⇒ Integer
Returns the denominator (always positive).
1998 1999 2000 2001 2002 |
# File 'rational.c', line 1998
static VALUE
numeric_denominator(VALUE self)
{
return f_denominator(f_to_r(self));
}
|
#div(numeric) ⇒ Integer
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.
600 601 602 603 604 605 |
# File 'numeric.c', line 600
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);
}
|
#divmod(numeric) ⇒ Array
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 negative 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]
693 694 695 696 697 |
# File 'numeric.c', line 693
static VALUE
num_divmod(VALUE x, VALUE y)
{
return rb_assoc_new(num_div(x, y), num_modulo(x, y));
}
|
#dup ⇒ Numeric
Returns the receiver.
518 519 520 521 522 |
# File 'numeric.c', line 518
static VALUE
num_dup(VALUE x)
{
return x;
}
|
#eql?(numeric) ⇒ Boolean
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
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 |
# File 'numeric.c', line 1333
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);
}
|
#fdiv(numeric) ⇒ Float
Returns float division.
582 583 584 585 586 |
# File 'numeric.c', line 582
static VALUE
num_fdiv(VALUE x, VALUE y)
{
return rb_funcall(rb_Float(x), '/', 1, y);
}
|
#finite? ⇒ Boolean
Returns true
if num
is a finite number, otherwise returns false
.
806 807 808 809 810 |
# File 'numeric.c', line 806
static VALUE
num_finite_p(VALUE num)
{
return Qtrue;
}
|
#floor([ndigits]) ⇒ Integer, Float
Returns the largest number less than or equal to num
with a precision of ndigits
decimal digits (default: 0).
Numeric implements this by converting its value to a Float and invoking Float#floor.
2437 2438 2439 2440 2441 |
# File 'numeric.c', line 2437
static VALUE
num_floor(int argc, VALUE *argv, VALUE num)
{
return flo_floor(argc, argv, rb_Float(num));
}
|
#i ⇒ Complex(0]
Returns the corresponding imaginary number. Not available for complex numbers.
-42.i #=> (0-42i)
2.0.i #=> (0+2.0i)
551 552 553 554 555 |
# File 'numeric.c', line 551
static VALUE
num_imaginary(VALUE num)
{
return rb_complex_new(INT2FIX(0), num);
}
|
#imag ⇒ 0 #imaginary ⇒ 0
Returns zero.
2165 2166 2167 2168 2169 |
# File 'complex.c', line 2165
static VALUE
numeric_imag(VALUE self)
{
return INT2FIX(0);
}
|
#imag ⇒ 0 #imaginary ⇒ 0
Returns zero.
2165 2166 2167 2168 2169 |
# File 'complex.c', line 2165
static VALUE
numeric_imag(VALUE self)
{
return INT2FIX(0);
}
|
#infinite? ⇒ -1, ...
Returns nil
, -1, or 1 depending on whether the value is finite, -Infinity
, or +Infinity
.
819 820 821 822 823 |
# File 'numeric.c', line 819
static VALUE
num_infinite_p(VALUE num)
{
return Qnil;
}
|
#integer? ⇒ Boolean
Returns true
if num
is an Integer.
1.0.integer? #=> false
1.integer? #=> true
722 723 724 725 726 |
# File 'numeric.c', line 722
static VALUE
num_int_p(VALUE num)
{
return Qfalse;
}
|
#abs ⇒ Numeric #magnitude ⇒ Numeric
Returns the absolute value of num
.
12.abs #=> 12
(-34.56).abs #=> 34.56
-34.56.abs #=> 34.56
Numeric#magnitude is an alias for Numeric#abs.
742 743 744 745 746 747 748 749 |
# File 'numeric.c', line 742
static VALUE
num_abs(VALUE num)
{
if (rb_num_negative_int_p(num)) {
return num_funcall0(num, idUMinus);
}
return num;
}
|
#modulo(numeric) ⇒ Object
x.modulo(y)
means x-y*(x/y).floor
.
Equivalent to num.divmod(numeric)[1]
.
See Numeric#divmod.
618 619 620 621 622 623 624 |
# File 'numeric.c', line 618
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));
}
|
#negative? ⇒ Boolean
Returns true
if num
is less than 0.
872 873 874 875 876 |
# File 'numeric.c', line 872
static VALUE
num_negative_p(VALUE num)
{
return rb_num_negative_int_p(num) ? Qtrue : Qfalse;
}
|
#nonzero? ⇒ self?
Returns self
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"]
791 792 793 794 795 796 797 798 |
# File 'numeric.c', line 791
static VALUE
num_nonzero_p(VALUE num)
{
if (RTEST(num_funcall0(num, rb_intern("zero?")))) {
return Qnil;
}
return num;
}
|
#numerator ⇒ Integer
Returns the numerator.
1986 1987 1988 1989 1990 |
# File 'rational.c', line 1986
static VALUE
numeric_numerator(VALUE self)
{
return f_numerator(f_to_r(self));
}
|
#arg ⇒ 0, Float #angle ⇒ 0, Float #phase ⇒ 0, Float
Returns 0 if the value is positive, pi otherwise.
2191 2192 2193 2194 2195 2196 2197 |
# File 'complex.c', line 2191
static VALUE
numeric_arg(VALUE self)
{
if (f_positive_p(self))
return INT2FIX(0);
return DBL2NUM(M_PI);
}
|
#polar ⇒ Array
Returns an array; [num.abs, num.arg].
2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 |
# File 'complex.c', line 2220
static VALUE
numeric_polar(VALUE self)
{
VALUE abs, arg;
if (RB_INTEGER_TYPE_P(self)) {
abs = rb_int_abs(self);
arg = numeric_arg(self);
}
else if (RB_FLOAT_TYPE_P(self)) {
abs = rb_float_abs(self);
arg = float_arg(self);
}
else if (RB_TYPE_P(self, T_RATIONAL)) {
abs = rb_rational_abs(self);
arg = numeric_arg(self);
}
else {
abs = f_abs(self);
arg = f_arg(self);
}
return rb_assoc_new(abs, arg);
}
|
#positive? ⇒ Boolean
Returns true
if num
is greater than 0.
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 |
# File 'numeric.c', line 849
static VALUE
num_positive_p(VALUE num)
{
const ID mid = '>';
if (FIXNUM_P(num)) {
if (method_basic_p(rb_cInteger))
return (SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0) ? Qtrue : Qfalse;
}
else if (RB_TYPE_P(num, T_BIGNUM)) {
if (method_basic_p(rb_cInteger))
return BIGNUM_POSITIVE_P(num) && !rb_bigzero_p(num) ? Qtrue : Qfalse;
}
return rb_num_compare_with_zero(num, mid);
}
|
#quo(int_or_rat) ⇒ Object #quo(flo) ⇒ Object
Returns the most exact division (rational for integers, float for floats).
2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 |
# File 'rational.c', line 2013
VALUE
rb_numeric_quo(VALUE x, VALUE y)
{
if (RB_TYPE_P(x, T_COMPLEX)) {
return rb_complex_div(x, y);
}
if (RB_FLOAT_TYPE_P(y)) {
return rb_funcallv(x, idFdiv, 1, &y);
}
if (canonicalization) {
x = rb_rational_raw1(x);
}
else {
x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
}
return nurat_div(x, y);
}
|
#real ⇒ self
Returns self.
2152 2153 2154 2155 2156 |
# File 'complex.c', line 2152
static VALUE
numeric_real(VALUE self)
{
return self;
}
|
#real? ⇒ Boolean
Returns true
if num
is a real number (i.e. not Complex).
706 707 708 709 710 |
# File 'numeric.c', line 706
static VALUE
num_real_p(VALUE num)
{
return Qtrue;
}
|
#rect ⇒ Array #rectangular ⇒ Array
Returns an array; [num, 0].
2206 2207 2208 2209 2210 |
# File 'complex.c', line 2206
static VALUE
numeric_rect(VALUE self)
{
return rb_assoc_new(self, INT2FIX(0));
}
|
#rect ⇒ Array #rectangular ⇒ Array
Returns an array; [num, 0].
2206 2207 2208 2209 2210 |
# File 'complex.c', line 2206
static VALUE
numeric_rect(VALUE self)
{
return rb_assoc_new(self, INT2FIX(0));
}
|
#remainder(numeric) ⇒ Object
x.remainder(y)
means x-y*(x/y).truncate
.
See Numeric#divmod.
635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
# File 'numeric.c', line 635
static VALUE
num_remainder(VALUE x, VALUE y)
{
VALUE z = num_funcall1(x, '%', y);
if ((!rb_equal(z, INT2FIX(0))) &&
((rb_num_negative_int_p(x) &&
rb_num_positive_int_p(y)) ||
(rb_num_positive_int_p(x) &&
rb_num_negative_int_p(y)))) {
return rb_funcall(z, '-', 1, y);
}
return z;
}
|
#round([ndigits]) ⇒ Integer, Float
Returns num
rounded to the nearest value with a precision of ndigits
decimal digits (default: 0).
Numeric implements this by converting its value to a Float and invoking Float#round.
2471 2472 2473 2474 2475 |
# File 'numeric.c', line 2471
static VALUE
num_round(int argc, VALUE* argv, VALUE num)
{
return flo_round(argc, argv, rb_Float(num));
}
|
#singleton_method_added(name) ⇒ Object
:nodoc:
Trap attempts to add methods to Numeric objects. Always raises a TypeError.
Numerics should be values; singleton_methods should not be added to them.
481 482 483 484 485 486 487 488 489 490 491 492 493 |
# File 'numeric.c', line 481
static VALUE
num_sadded(VALUE x, VALUE name)
{
ID mid = rb_to_id(name);
/* ruby_frame = ruby_frame->prev; */ /* pop frame for "singleton_method_added" */
rb_remove_method_id(rb_singleton_class(x), mid);
rb_raise(rb_eTypeError,
"can't define singleton method \"%"PRIsVALUE"\" for %"PRIsVALUE,
rb_id2str(mid),
rb_obj_class(x));
UNREACHABLE_RETURN(Qnil);
}
|
#step(by: step, to: limit) {|i| ... } ⇒ self #step(by: step, to: limit) ⇒ Object #step(by: step, to: limit) ⇒ Object #step(limit = nil, step = 1) {|i| ... } ⇒ self #step(limit = nil, step = 1) ⇒ Object #step(limit = nil, step = 1) ⇒ Object
Invokes the given block with the sequence of numbers starting at num
, incremented by step
(defaulted to 1
) 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), where limit
is defaulted to infinity.
In the recommended keyword argument style, either or both of step
and limit
(default infinity) can be omitted. In the fixed position argument style, zero as a step (i.e. num.step(limit, 0)
) is not allowed for historical compatibility reasons.
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*Float::EPSILON) + 1 times, where n = (limit - num)/step.
Otherwise, the loop starts at num
, uses either the less-than (<
) or greater-than (>
) operator to compare the counter against limit
, and increments itself using the +
operator.
If no block is given, an Enumerator is returned instead. Especially, the enumerator is an Enumerator::ArithmeticSequence if both limit
and step
are kind of Numeric or nil
.
For example:
p 1.step.take(4)
p 10.step(by: -1).take(4)
3.step(to: 5) {|i| print i, " " }
1.step(10, 2) {|i| print i, " " }
Math::E.step(to: Math::PI, by: 0.2) {|f| print f, " " }
Will produce:
[1, 2, 3, 4]
[10, 9, 8, 7]
3 4 5
1 3 5 7 9
2.718281828459045 2.9182818284590453 3.118281828459045
2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 |
# File 'numeric.c', line 2750
static VALUE
num_step(int argc, VALUE *argv, VALUE from)
{
VALUE to, step;
int desc, inf;
if (!rb_block_given_p()) {
VALUE by = Qundef;
num_step_extract_args(argc, argv, &to, &step, &by);
if (by != Qundef) {
step = by;
}
if (NIL_P(step)) {
step = INT2FIX(1);
}
if ((NIL_P(to) || rb_obj_is_kind_of(to, rb_cNumeric)) &&
rb_obj_is_kind_of(step, rb_cNumeric)) {
return rb_arith_seq_new(from, ID2SYM(rb_frame_this_func()), argc, argv,
num_step_size, from, to, step, FALSE);
}
return SIZED_ENUMERATOR(from, 2, ((VALUE [2]){to, step}), num_step_size);
}
desc = num_step_scan_args(argc, argv, &to, &step, TRUE, FALSE);
if (rb_equal(step, INT2FIX(0))) {
inf = 1;
}
else if (RB_TYPE_P(to, T_FLOAT)) {
double f = RFLOAT_VALUE(to);
inf = isinf(f) && (signbit(f) ? desc : !desc);
}
else inf = 0;
if (FIXNUM_P(from) && (inf || FIXNUM_P(to)) && FIXNUM_P(step)) {
long i = FIX2LONG(from);
long diff = FIX2LONG(step);
if (inf) {
for (;; i += diff)
rb_yield(LONG2FIX(i));
}
else {
long end = FIX2LONG(to);
if (desc) {
for (; i >= end; i += diff)
rb_yield(LONG2FIX(i));
}
else {
for (; i <= end; i += diff)
rb_yield(LONG2FIX(i));
}
}
}
else if (!ruby_float_step(from, to, step, FALSE, FALSE)) {
VALUE i = from;
if (inf) {
for (;; i = rb_funcall(i, '+', 1, step))
rb_yield(i);
}
else {
ID cmp = desc ? '<' : '>';
for (; !RTEST(rb_funcall(i, cmp, 1, to)); i = rb_funcall(i, '+', 1, step))
rb_yield(i);
}
}
return from;
}
|
#to_c ⇒ Object
Returns the value as a complex.
1697 1698 1699 1700 1701 |
# File 'complex.c', line 1697
static VALUE
numeric_to_c(VALUE self)
{
return rb_complex_new1(self);
}
|
#to_int ⇒ Integer
Invokes the child class’s to_i
method to convert num
to an integer.
1.0.class #=> Float
1.0.to_int.class #=> Integer
1.0.to_i.class #=> Integer
836 837 838 839 840 |
# File 'numeric.c', line 836
static VALUE
num_to_int(VALUE num)
{
return num_funcall0(num, id_to_i);
}
|
#truncate([ndigits]) ⇒ Integer, Float
Returns num
truncated (toward zero) to a precision of ndigits
decimal digits (default: 0).
Numeric implements this by converting its value to a Float and invoking Float#truncate.
2488 2489 2490 2491 2492 |
# File 'numeric.c', line 2488
static VALUE
num_truncate(int argc, VALUE *argv, VALUE num)
{
return flo_truncate(argc, argv, rb_Float(num));
}
|
#zero? ⇒ Boolean
Returns true
if num
has a zero value.
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 |
# File 'numeric.c', line 758
static VALUE
num_zero_p(VALUE num)
{
if (FIXNUM_P(num)) {
if (FIXNUM_ZERO_P(num)) {
return Qtrue;
}
}
else if (RB_TYPE_P(num, T_BIGNUM)) {
if (rb_bigzero_p(num)) {
/* this should not happen usually */
return Qtrue;
}
}
else if (rb_equal(num, INT2FIX(0))) {
return Qtrue;
}
return Qfalse;
}
|