Spec-Zone.ru › Ruby 3.4

класс Numeric

Родитель:
Объект
Включенные модули:
Comparable

Numeric — это класс, от которого должны наследоваться все числовые классы более высокого уровня.

Numeric позволяет создавать экземпляры объектов, размещённых в куче. Другие основные числовые классы, такие как Integer, реализованы как непосредственные объекты, что означает, что каждый Integer является одним единственным неизменяемым объектом, который всегда передаётся по значению.

a = 1
1.object_id == a.object_id   #=> true

Может существовать только один экземпляр целого числа 1, например. Ruby гарантирует это, предотвращая создание экземпляров. Если попытка дублирования всё же будет сделана, возвращается тот же экземпляр.

Integer.new(1)                   #=> NoMethodError: undefined method `new' for Integer:Class
1.dup                            #=> 1
1.object_id == 1.dup.object_id   #=> true

По этой причине Numeric следует использовать при определении других числовых классов.

Классы, которые наследуются от Numeric, должны реализовать coerce, который возвращает двучленный Array, содержащий объект, преобразованный в экземпляр нового класса, и self (см. coerce).

Наследуемые классы также должны реализовать методы арифметических операторов (+, -, * и /) и оператор <=> (см. Comparable). Эти методы могут опираться на coerce для обеспечения взаимодействия с экземплярами других числовых классов.

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

Что здесь есть

Прежде всего, что есть где-то ещё. Класс Numeric:

  • Наследует от класса Объект.

  • Включает модуль Comparable.

Здесь класс Numeric предоставляет методы для:

  • Запросов

  • Сравнения

  • Преобразований

  • Других

Запросы

  • finite?: Возвращает true, если self не бесконечен и не является числом.

  • infinite?: Возвращает -1, nil или +1 в зависимости от того, является ли self -Infinity<tt>, finite, or <tt>+Infinity.

  • integer?: Возвращает, является ли self целым числом.

  • negative?: Возвращает, является ли self отрицательным.

  • nonzero?: Возвращает, не равно ли self нулю.

  • positive?: Возвращает, является ли self положительным.

  • real?: Возвращает, является ли self действительным значением.

  • zero?: Возвращает, равно ли self нулю.

Сравнения

  • <=>: Возвращает:

    • -1, если self меньше заданного значения.

    • 0, если self равно заданному значению.

    • 1, если self больше заданного значения.

    • nil, если self и заданное значение не сравнимы.

  • eql?: Возвращает, имеют ли self и заданное значение одинаковое значение и тип.

Преобразования

  • % (алиас modulo): Возвращает остаток от деления self на заданное значение.

  • -@: Возвращает значение self, сменённое на противоположное.

  • abs (алиас magnitude): Возвращает абсолютное значение self.

  • abs2: Возвращает квадрат self.

  • angle (алиас arg и phase): Возвращает 0, если self положительно, Math::PI в противном случае.

  • ceil: Возвращает наименьшее число, большее или равное self, с заданной точностью.

  • coerce: Возвращает массив [coerced_self, coerced_other] для заданного другого значения.

  • conj (алиас conjugate): Возвращает комплексно сопряжённое значение self.

  • denominator: Возвращает знаменатель (всегда положительный) представления Rational self.

  • div: Возвращает результат деления self на заданное значение, преобразованный в целое число.

  • divmod: Возвращает массив [quotient, modulus] в результате деления self на заданный делитель.

  • fdiv: Возвращает Float результат деления self на заданный делитель.

  • floor: Возвращает наибольшее число, меньшее или равное self, с заданной точностью.

  • i: Возвращает объект Complex Complex(0, self). для заданного значения.

  • imaginary (алиас imag): Возвращает мнимую часть self.

  • numerator: Возвращает числитель представления Rational self; имеет тот же знак, что и self.

  • polar: Возвращает массив [self.abs, self.arg].

  • quo: Возвращает значение self, делённое на заданное значение.

  • real: Возвращает действительную часть self.

  • rect (алиас rectangular): Возвращает массив [self, 0].

  • remainder: Возвращает self-arg*(self/arg).truncate для заданного arg.

  • round: Возвращает значение self, округлённое до ближайшего значения с заданной точностью.

  • to_c: Возвращает Complex представление self.

  • to_int: Возвращает Integer представление self, с усечением при необходимости.

  • truncate: Возвращает self, усечённое (к нулю) до заданной точности.

Другие

  • clone: Возвращает self; заморозку запрещает.

  • dup (алиас +@): Возвращает self.

  • step: Вызывает заданный блок с последовательностью указанных чисел.

Публичные методы экземпляра

self % other → real_numeric
Исходный код
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));
}

Возвращает self по модулю other как действительное число.

Из базовых и стандартных классов библиотеки только Rational использует эту реализацию.

Для Rational r и действительного числа n, эти выражения эквивалентны:

r % n
r-n*(r/n).floor
r.divmod(n)[1]

См. Numeric#divmod.

Примеры:

r = Rational(1, 2)    # => (1/2)
r2 = Rational(2, 3)   # => (2/3)
r % r2                # => (1/2)
r % 2                 # => (1/2)
r % 2.0               # => 0.5

r = Rational(301,100) # => (301/100)
r2 = Rational(7,5)    # => (7/5)
r % r2                # => (21/100)
r % -r2               # => (-119/100)
(-r) % r2             # => (119/100)
(-r) %-r2             # => (-21/100)
Также используется как: modulo
+self → self
Исходный код
# File numeric.rb, line 89
def +@
  self
end

Возвращает self.

-self → numeric
Исходный код
static VALUE
num_uminus(VALUE num)
{
    VALUE zero;

    zero = INT2FIX(0);
    do_coerce(&zero, &num, TRUE);

    return num_funcall1(zero, '-', num);
}

Унарный минус — возвращает принимающий объект с обратным знаком.

self <=> other → zero or nil
Исходный код
static VALUE
num_cmp(VALUE x, VALUE y)
{
    if (x == y) return INT2FIX(0);
    return Qnil;
}

Возвращает ноль, если self совпадает с other, nil в противном случае.

Ни один подкласс в ядре Ruby или стандартной библиотеке не использует эту реализацию.

abs → numeric
Исходный код
static VALUE
num_abs(VALUE num)
{
    if (rb_num_negative_int_p(num)) {
        return num_funcall0(num, idUMinus);
    }
    return num;
}

Возвращает абсолютное значение self.

12.abs        #=> 12
(-34.56).abs  #=> 34.56
-34.56.abs    #=> 34.56
Также используется как: magnitude
abs2 → real
Исходный код
static VALUE
numeric_abs2(VALUE self)
{
    return f_mul(self, self);
}

Возвращает квадрат self.

angle
Псевдоним для: arg
arg → 0 or Math::PI
Исходный код
static VALUE
numeric_arg(VALUE self)
{
    if (f_positive_p(self))
        return INT2FIX(0);
    return DBL2NUM(M_PI);
}

Возвращает ноль, если self положителен, Math::PI в противном случае.

Также используется как: angle, phase
ceil(ndigits = 0) → float or integer
Исходный код
static VALUE
num_ceil(int argc, VALUE *argv, VALUE num)
{
    return flo_ceil(argc, argv, rb_Float(num));
}

Возвращает наименьшее число с плавающей точкой или целое число, которое больше или равно self, как указано заданным ‘ndigits’, который должен быть объектом, преобразуемым в целое число.

Эквивалентно self.to_f.ceil(ndigits).

Связанные: floor, Float#ceil.

clone(freeze: true) → self
Исходный код
static VALUE
num_clone(int argc, VALUE *argv, VALUE x)
{
    return rb_immutable_obj_clone(argc, argv, x);
}

Возвращает self.

Вызывает исключение, если значение для freeze не является ни true, ни nil.

Связанные: Numeric#dup.

coerce(other) → array
Исходный код
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);
}

Возвращает 2-элементный массив, содержащий два числовых элемента, сформированных из двух операндов self и other, общего совместимого типа.

Из базовых и стандартных классов библиотеки, Integer, Rational и Complex используют эту реализацию.

Примеры:

i = 2                    # => 2
i.coerce(3)              # => [3, 2]
i.coerce(3.0)            # => [3.0, 2.0]
i.coerce(Rational(1, 2)) # => [0.5, 2.0]
i.coerce(Complex(3, 4))  # Raises RangeError.

r = Rational(5, 2)       # => (5/2)
r.coerce(2)              # => [(2/1), (5/2)]
r.coerce(2.0)            # => [2.0, 2.5]
r.coerce(Rational(2, 3)) # => [(2/3), (5/2)]
r.coerce(Complex(3, 4))  # => [(3+4i), ((5/2)+0i)]

c = Complex(2, 3)        # => (2+3i)
c.coerce(2)              # => [(2+0i), (2+3i)]
c.coerce(2.0)            # => [(2.0+0i), (2+3i)]
c.coerce(Rational(1, 2)) # => [((1/2)+0i), (2+3i)]
c.coerce(Complex(3, 4))  # => [(3+4i), (2+3i)]

Вызывает исключение, если происходит ошибка преобразования типа.

conj → self
Псевдоним для: conjugate
conjugate
Исходный код
Также используется как: conj
denominator → integer
Исходный код
static VALUE
numeric_denominator(VALUE self)
{
    return f_denominator(f_to_r(self));
}

Возвращает знаменатель (всегда положительный).

div(other) → integer
Исходный код
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);
}

Возвращает частное self/other как целое число (через floor), используя метод / в производном классе self. (Сам Numeric не определяет метод /.)

Из базовых и стандартных классов библиотеки только Float и Rational используют эту реализацию.

divmod(other) → array
Исходный код
static VALUE
num_divmod(VALUE x, VALUE y)
{
    return rb_assoc_new(num_div(x, y), num_modulo(x, y));
}

Возвращает 2-элементный массив [q, r], где

q = (self/other).floor                  # Quotient
r = self % other                        # Remainder

Из базовых и стандартных классов библиотеки только Rational использует эту реализацию.

Примеры:

Rational(11, 1).divmod(4)               # => [2, (3/1)]
Rational(11, 1).divmod(-4)              # => [-3, (-1/1)]
Rational(-11, 1).divmod(4)              # => [-3, (1/1)]
Rational(-11, 1).divmod(-4)             # => [2, (-3/1)]

Rational(12, 1).divmod(4)               # => [3, (0/1)]
Rational(12, 1).divmod(-4)              # => [-3, (0/1)]
Rational(-12, 1).divmod(4)              # => [-3, (0/1)]
Rational(-12, 1).divmod(-4)             # => [3, (0/1)]

Rational(13, 1).divmod(4.0)             # => [3, 1.0]
Rational(13, 1).divmod(Rational(4, 11)) # => [35, (3/11)]
dup → self
Исходный код
# File numeric.rb, line 9
def dup
  self
end

Возвращает self.

Связанные: Numeric#clone.

eql?(other) → true or false
Исходный код
static VALUE
num_eql(VALUE x, VALUE y)
{
    if (TYPE(x) != TYPE(y)) return Qfalse;

    if (RB_BIGNUM_TYPE_P(x)) {
        return rb_big_eql(x, y);
    }

    return rb_equal(x, y);
}

Возвращает true если self и other одного типа и имеют равные значения.

Из классов ядра и стандартной библиотеки, только Integer, Rational и Complex используют эту реализацию.

Примеры:

1.eql?(1)              # => true
1.eql?(1.0)            # => false
1.eql?(Rational(1, 1)) # => false
1.eql?(Complex(1, 0))  # => false

Метод eql? отличается от == тем, что eql? требует совпадения типов, в то время как == - нет.

fdiv(other) → float
Исходный код
static VALUE
num_fdiv(VALUE x, VALUE y)
{
    return rb_funcall(rb_Float(x), '/', 1, y);
}

Возвращает частное self/other в виде числа с плавающей точкой, используя метод / в производном классе self. (Сам Numeric не определяет метод /.)

Из классов ядра и стандартной библиотеки, только BigDecimal использует эту реализацию.

finite? → true or false
Исходный код
# File numeric.rb, line 48
def finite?
  true
end

Возвращает true если self является конечным числом, false в противном случае.

floor(ndigits = 0) → float or integer
Исходный код
static VALUE
num_floor(int argc, VALUE *argv, VALUE num)
{
    return flo_floor(argc, argv, rb_Float(num));
}

Возвращает наибольшее число с плавающей точкой или целое число, которое меньше или равно self, как указано заданным ‘ndigits’, который должен быть объектом, преобразуемым в целое число.

Эквивалентно self.to_f.floor(ndigits).

Связанные: ceil, Float#floor.

i → complex
Исходный код
static VALUE
num_imaginary(VALUE num)
{
    return rb_complex_new(INT2FIX(0), num);
}

Возвращает Complex(0, self):

2.i              # => (0+2i)
-2.i             # => (0-2i)
2.0.i            # => (0+2.0i)
Rational(1, 2).i # => (0+(1/2)*i)
Complex(3, 4).i  # Raises NoMethodError.
imag → 0
Псевдоним для: imaginary
imaginary
Исходный код
Также является псевдонимом для: imag
infinite? → -1, 1, or nil
Исходный код
# File numeric.rb, line 58
def infinite?
  nil
end

Возвращает nil, -1 или 1 в зависимости от того, является ли self конечным, -Infinity или +Infinity.

integer? → true or false
Исходный код
# File numeric.rb, line 39
def integer?
  false
end

Возвращает true если self является Integer.

1.0.integer? # => false
1.integer?   # => true
magnitude
Псевдоним для: abs
modulo
Псевдоним для: %
negative? → true or false
Исходный код
static VALUE
num_negative_p(VALUE num)
{
    return RBOOL(rb_num_negative_int_p(num));
}

Возвращает true если self меньше 0, false в противном случае.

nonzero? → self or nil
Исходный код
static VALUE
num_nonzero_p(VALUE num)
{
    if (RTEST(num_funcall0(num, rb_intern("zero?")))) {
        return Qnil;
    }
    return num;
}
Returns +self+ if +self+ is not a zero value, +nil+ otherwise;
uses method <tt>zero?</tt> for the evaluation.

The returned +self+ allows the method to be chained:

  a = %w[z Bb bB bb BB a aA Aa AA A]
  a.sort {|a, b| (a.downcase <=> b.downcase).nonzero? || a <=> b }
  # => ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"]

Of the Core and Standard Library classes,
Integer, Float, Rational, and Complex use this implementation.

Связанные: zero?

numerator → integer
Исходный код
static VALUE
numeric_numerator(VALUE self)
{
    return f_numerator(f_to_r(self));
}

Возвращает числитель.

phase
Псевдоним для: arg
polar → array
Исходный код
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);
}

Возвращает массив [self.abs, self.arg].

positive? → true or false
Исходный код
static VALUE
num_positive_p(VALUE num)
{
    const ID mid = '>';

    if (FIXNUM_P(num)) {
        if (method_basic_p(rb_cInteger))
            return RBOOL((SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0));
    }
    else if (RB_BIGNUM_TYPE_P(num)) {
        if (method_basic_p(rb_cInteger))
            return RBOOL(BIGNUM_POSITIVE_P(num) && !rb_bigzero_p(num));
    }
    return rb_num_compare_with_zero(num, mid);
}

Возвращает true если self больше 0, false в противном случае.

quo(int_or_rat) → rat
quo(flo) → flo
Исходный код
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);
    }

    x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
    return rb_rational_div(x, y);
}

Возвращает наиболее точное деление (рациональное для целых чисел, число с плавающей точкой для чисел с плавающей точкой).

real → self
Исходный код
# File numeric.rb, line 27
def real
  self
end

Возвращает self.

real? → true или false
Исходный код
# File numeric.rb, line 18
def real?
  true
end

Возвращает значение true, если self является действительным числом (то есть не Complex).

rect → массив

Возвращает массив [self, 0].

Псевдоним для: rectangular
rectangular
Исходный код
Также псевдоним: rect
remainder(other) → действительное_число
Исходный код
static VALUE
num_remainder(VALUE x, VALUE y)
{
    if (!rb_obj_is_kind_of(y, rb_cNumeric)) {
        do_coerce(&x, &y, TRUE);
    }
    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)))) {
        if (RB_FLOAT_TYPE_P(y)) {
            if (isinf(RFLOAT_VALUE(y))) {
                return x;
            }
        }
        return rb_funcall(z, '-', 1, y);
    }
    return z;
}

Возвращает остаток от деления self на other.

Из классов Ядра и Стандартной библиотеки, только Float и Rational используют данную реализацию.

Примеры:

11.0.remainder(4)              # => 3.0
11.0.remainder(-4)             # => 3.0
-11.0.remainder(4)             # => -3.0
-11.0.remainder(-4)            # => -3.0

12.0.remainder(4)              # => 0.0
12.0.remainder(-4)             # => 0.0
-12.0.remainder(4)             # => -0.0
-12.0.remainder(-4)            # => -0.0

13.0.remainder(4.0)            # => 1.0
13.0.remainder(Rational(4, 1)) # => 1.0

Rational(13, 1).remainder(4)   # => (1/1)
Rational(13, 1).remainder(-4)  # => (1/1)
Rational(-13, 1).remainder(4)  # => (-1/1)
Rational(-13, 1).remainder(-4) # => (-1/1)
round(digits = 0) → целое или вещественное
Исходный код
static VALUE
num_round(int argc, VALUE* argv, VALUE num)
{
    return flo_round(argc, argv, rb_Float(num));
}

Возвращает self, округлённое до ближайшего значения с точностью digits десятичных знаков.

Numeric реализует это, преобразуя self в Float и вызывая Float#round.

step(to = nil, by = 1) {|n| ... } → self
step(to = nil, by = 1) → перечисление
step(to = nil, by: 1) {|n| ... } → self
step(to = nil, by: 1) → перечисление
step(by: 1, to: ) {|n| ... } → self
step(by: 1, to: ) → перечисление
step(by: , to: nil) {|n| ... } → self
step(by: , to: nil) → перечисление
Исходный код
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 (!UNDEF_P(by)) {
            step = by;
        }
        if (NIL_P(step)) {
            step = INT2FIX(1);
        }
        else if (rb_equal(step, INT2FIX(0))) {
            rb_raise(rb_eArgError, "step can't be 0");
        }
        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_KW(from, 2, ((VALUE [2]){to, step}), num_step_size, FALSE);
    }

    desc = num_step_scan_args(argc, argv, &to, &step, TRUE, FALSE);
    if (rb_equal(step, INT2FIX(0))) {
        inf = 1;
    }
    else if (RB_FLOAT_TYPE_P(to)) {
        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;
}

Генерирует последовательность чисел; при наличии блока, проходит по последовательности.

Из классов Ядра и Стандартной библиотеки, Integer, Float, и Rational используют данную реализацию.

Быстрый пример:

squares = []
1.step(by: 2, to: 10) {|i| squares.push(i*i) }
squares # => [1, 9, 25, 49, 81]

Сгенерированная последовательность:

  • Начинается с self.

  • Продолжается с интервалами by (который может быть не равен нулю).

  • Заканчивается последним числом, которое находится в пределах или равно to; то есть меньше или равно to если by положительно, больше или равно to если by отрицательно. Если to равно nil, последовательность бесконечна.

Если блок задан, вызывает блок с каждым числом в последовательности; возвращает self. Если блок не задан, возвращает Enumerator::ArithmeticSequence.

Ключевые аргументы

С ключевыми аргументами by и to, их значения (или значения по умолчанию) определяют шаг и предел:

# Both keywords given.
squares = []
4.step(by: 2, to: 10) {|i| squares.push(i*i) }    # => 4
squares # => [16, 36, 64, 100]
cubes = []
3.step(by: -1.5, to: -3) {|i| cubes.push(i*i*i) } # => 3
cubes   # => [27.0, 3.375, 0.0, -3.375, -27.0]
squares = []
1.2.step(by: 0.2, to: 2.0) {|f| squares.push(f*f) }
squares # => [1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0]

squares = []
Rational(6/5).step(by: 0.2, to: 2.0) {|r| squares.push(r*r) }
squares # => [1.0, 1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0]

# Only keyword to given.
squares = []
4.step(to: 10) {|i| squares.push(i*i) }           # => 4
squares # => [16, 25, 36, 49, 64, 81, 100]
# Only by given.

# Only keyword by given
squares = []
4.step(by:2) {|i| squares.push(i*i); break if i > 10 }
squares # => [16, 36, 64, 100, 144]

# No block given.
e = 3.step(by: -1.5, to: -3) # => (3.step(by: -1.5, to: -3))
e.class                      # => Enumerator::ArithmeticSequence

Позиционные аргументы

С необязательными позиционными аргументами to и by, их значения (или значения по умолчанию) определяют шаг и предел:

squares = []
4.step(10, 2) {|i| squares.push(i*i) }    # => 4
squares # => [16, 36, 64, 100]
squares = []
4.step(10) {|i| squares.push(i*i) }
squares # => [16, 25, 36, 49, 64, 81, 100]
squares = []
4.step {|i| squares.push(i*i); break if i > 10 }  # => nil
squares # => [16, 25, 36, 49, 64, 81, 100, 121]

Примечания по реализации

Если все аргументы являются целыми числами, цикл работает с помощью целочисленного счётчика.

Если хотя бы один из аргументов является дробным числом, все они преобразуются в числа с плавающей точкой, и цикл выполняется floor(n + n*Float::EPSILON) + 1 раз, где n = (предел - self)/шаг.

to_c → комплексное
Исходный код
static VALUE
numeric_to_c(VALUE self)
{
    return rb_complex_new1(self);
}

Возвращает self как объект Complex.

to_int → целое
Исходный код
static VALUE
num_to_int(VALUE num)
{
    return num_funcall0(num, id_to_i);
}

Возвращает self как целое число; преобразует с использованием метода to_i в производном классе.

Из классов Ядра и Стандартной библиотеки, только Rational и Complex используют данную реализацию.

Примеры:

Rational(1, 2).to_int # => 0
Rational(2, 1).to_int # => 2
Complex(2, 0).to_int  # => 2
Complex(2, 1).to_int  # Raises RangeError (non-zero imaginary part)
truncate(digits = 0) → целое или вещественное
Исходный код
static VALUE
num_truncate(int argc, VALUE *argv, VALUE num)
{
    return flo_truncate(argc, argv, rb_Float(num));
}

Возвращает self, усечённое (к нулю) с точностью digits десятичных знаков.

Numeric реализует это, преобразуя self в Float и вызывая Float#truncate.

zero? → true или false
Исходный код
static VALUE
num_zero_p(VALUE num)
{
    return rb_equal(num, INT2FIX(0));
}

Возвращает true если zero имеет нулевое значение, false в противном случае.

Из классов Ядра и Стандартной библиотеки, только Rational и Complex используют данную реализацию.

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API