Ruby 2.4

Numeric

class Numeric

Parent:ObjectIncluded modules:Comparable

数字是所有高级数字类应该继承的类。

数字允许实例化堆分配的对象。其他核心数字类(如Integer)实现为立即数,这意味着每个Integer都是一个总是按值传递的单个不可变对象。

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

例如,只能有一个整数1实例。Ruby通过防止实例化和重复来确保这一点。

Integer.new(1) #=> NoMethodError: undefined method `new' for Integer:Class 1.dup #=> TypeError: can't dup Integer

出于这个原因,在定义其他数字类时应该使用数字。

从Numeric继承的类必须实现coerce,它返回一个包含被强制到新类实例中的对象的两个成员数组self(参见胁迫)。

继承类也应该实现算术运算符方法(+,-,*和/)和<=>运算符(见可比)。这些方法可能依赖于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

公共实例方法

modulo(numeric) → real Show source

x.modulo(y) means x-y*(x/y).floor

Equivalent to num.divmod(numeric)[1].

See #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) }

+num → num Show source

Unary Plus - 返回接收者的值。

static VALUE num_uplus(VALUE num) { return num; }

-num → numeric Show source

Unary Minus—- 返回接收器的值,否定。

static VALUE num_uminus(VALUE num) { VALUE zero; zero = INT2FIX(0 do_coerce(&zero, &num, TRUE return num_funcall1(zero, '-', num }

number <=> other → 0 or nil Show source

如果number等于other,则返回零;否则nil,如果两个值不可比较,则返回。

static VALUE num_cmp(VALUE x, VALUE y) { if (x == y) return INT2FIX(0 return Qnil; }

abs → numeric Show source

返回的绝对值num

12.abs #=> 12 (-34.56).abs #=> 34.56 -34.56.abs #=> 34.56

#magnitude是#abs的别名。

static VALUE num_abs(VALUE num) { if (negative_int_p(num)) { return num_funcall0(num, idUMinus } return num; }

abs2 → real Show source

返回自我的平方。

static VALUE numeric_abs2(VALUE self) { return f_mul(self, self }

angle → 0 or float Show source

如果值为正,则返回0,否则返回pi。

static VALUE numeric_arg(VALUE self) { if (f_positive_p(self)) return INT2FIX(0 return DBL2NUM(M_PI }

arg → 0 or float Show source

如果值为正,则返回0,否则返回pi。

static VALUE numeric_arg(VALUE self) { if (f_positive_p(self)) return INT2FIX(0 return DBL2NUM(M_PI }

ceil(ndigits) → integer or float Show source

返回大于或等于的最小可能整数num

数字通过将其自身转换为Float然后调用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) }

coerce(numeric) → array Show source

如果numeric与type相同num,则返回包含numericand 的数组num。否则,返回一个包含a numericnum表示为Float对象的数组。

Ruby使用这种强制机制来处理混合类型的数字操作:它旨在找到操作符的两个操作数之间的兼容通用类型。

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 }

conj → self Show source

conjugate → self

返回本身。

static VALUE numeric_conj(VALUE self) { return self; }

conjugate → self Show source

返回本身。

static VALUE numeric_conj(VALUE self) { return self; }

denominator → integer Show source

返回分母(总是正数)。

static VALUE numeric_denominator(VALUE self) { return f_denominator(f_to_r(self) }

div(numeric) → integer Show source

用于/执行除法,然后将结果转换为整数。numeric没有定义/操作员; 这留给子类。

Equivalent to num.divmod(numeric)[0].

See #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 }

divmod(numeric) → array Show source

返回包含通过分割获得的商和模量的阵列num通过numeric

If q, r = * x.divmod(y), then

q = floor(x/y) x = q*y+r

商被四舍五入到-infinity,如下表所示:

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) }

eql?(numeric) → true or false Show source

返回true如果numnumeric是相同的类型并具有相同的值。与此Numeric#==进行对比,执行类型转换。

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 }

fdiv(numeric) → float Show source

返回浮点除法。

static VALUE num_fdiv(VALUE x, VALUE y) { return rb_funcall(rb_Float(x), '/', 1, y }

finite? → true or false Show source

如果num是有限数字,则返回true,否则返回false。

static VALUE num_finite_p(VALUE num) { return Qtrue; }

floor(ndigits) → integer or float Show source

返回小于或等于的最大整数num

Numeric通过将Integer转换为Float并调用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) }

i → Complex(0,num) Show source

返回相应的虚数。不适用于复数。

static VALUE num_imaginary(VALUE num) { return rb_complex_new(INT2FIX(0), num }

imag → 0 Show source

imaginary → 0

返回零。

static VALUE numeric_imag(VALUE self) { return INT2FIX(0 }

imaginary → 0 Show source

返回零。

static VALUE numeric_imag(VALUE self) { return INT2FIX(0 }

infinite? → nil or 1 or -1 Show source

返回对应于num幅度值的值:

finite

nil

-Infinity

-1

+Infinity

+1

static VALUE num_infinite_p(VALUE num) { return Qnil; }

initialize_copy(p1) Show source

数字是不可改变的值,不应该被复制。

任何在Numeric上使用此方法的尝试都会引发TypeError。

static VALUE num_init_copy(VALUE x, VALUE y) { rb_raise(rb_eTypeError, "can't copy %"PRIsVALUE, rb_obj_class(x) UNREACHABLE; }

integer? → true or false Show source

如果num是整数,则返回true

(1.0).integer? #=> false (1).integer? #=> true

static VALUE num_int_p(VALUE num) { return Qfalse; }

magnitude → numeric Show source

返回的绝对值num

12.abs #=> 12 (-34.56).abs #=> 34.56 -34.56.abs #=> 34.56

#magnitude是#abs的别名。

static VALUE num_abs(VALUE num) { if (negative_int_p(num)) { return num_funcall0(num, idUMinus } return num; }

modulo(numeric) → real Show source

x.modulo(y) means x-y*(x/y).floor

相当于num.divmod(numeric)[1]

See #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) }

negative? → true or false Show source

返回true如果num小于0。

static VALUE num_negative_p(VALUE num) { return negative_int_p(num) ? Qtrue : Qfalse; }

nonzero? → self or nil Show source

如果num不是零nil则返回,否则返回self

这种行为在链接比较时很有用:

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(VALUE num) { if (RTEST(num_funcall0(num, rb_intern("zero?")))) { return Qnil; } return num; }

numerator → integer Show source

返回分子。

static VALUE numeric_numerator(VALUE self) { return f_numerator(f_to_r(self) }

phase → 0 or float Show source

如果值为正,则返回0,否则返回pi。

static VALUE numeric_arg(VALUE self) { if (f_positive_p(self)) return INT2FIX(0 return DBL2NUM(M_PI }

polar → array Show source

返回一个数组; num.abs,num.arg。

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? → true or false Show source

如果num大于0,则返回true

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 compare_with_zero(num, mid }

quo(int_or_rat) → rat Show source

quo(flo) → flo

返回最精确的划分(对于整数有理,浮点对浮点)。

static VALUE numeric_quo(VALUE x, VALUE y) { if (RB_FLOAT_TYPE_P(y)) { return rb_funcall(x, rb_intern("fdiv"), 1, y } #ifdef CANON if (canonicalization) { x = rb_rational_raw1(x } else #endif { x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r" } return nurat_div(x, y }

real → self Show source

返回自我本身。

static VALUE numeric_real(VALUE self) { return self; }

real? → true or false Show source

如果num是实数,则返回true。(即不复杂)。

static VALUE num_real_p(VALUE num) { return Qtrue; }

rect → array Show source

rectangular → array

返回一个数组; num,0。

static VALUE numeric_rect(VALUE self) { return rb_assoc_new(self, INT2FIX(0) }

rectangular → array Show source

返回一个数组; num,0。

static VALUE numeric_rect(VALUE self) { return rb_assoc_new(self, INT2FIX(0) }

remainder(numeric) → real Show source

x.remainder(y) means x-y*(x/y).truncate

See #divmod.

static VALUE num_remainder(VALUE x, VALUE y) { VALUE z = num_funcall1(x, '%', y if ((!rb_equal(z, INT2FIX(0))) && ((negative_int_p(x) && positive_int_p(y)) || (positive_int_p(x) && negative_int_p(y)))) { return rb_funcall(z, '-', 1, y } return z; }

round(ndigits) → integer or float Show source

num以十进制数字的形式舍入到给定的精度(默认为0位)。

精度可能是负面的。当ndigits大于零时返回一个浮点数。

Numeric implements this by converting itself to a Float and invoking Float#round.

static VALUE num_round(int argc, VALUE* argv, VALUE num) { return flo_round(argc, argv, rb_Float(num) }

singleton_method_added(p1) Show source

陷阱尝试向Numeric对象添加方法。总是引发TypeError。

数字应该是价值; 不应该将singleton_methods添加到它们中。

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; }

step(by: step, to: limit) {|i| block } → self Show source

step(by: step, to: limit) → an_enumerator

step(limit=nil, step=1) {|i| block } → self

step(limit=nil, step=1) → an_enumerator

调用与开始的数字序列的给定的块num,通过递增step(默认为1每个呼叫)。

当要传递给块的值大于limit(如果step为正值)或小于limit(如果step为负值)时,循环结束,其中限制默认为无穷大。

在推荐的关键字参数样式中,可以省略steplimit(默认无穷大)中的一个或两个。在固定位置参数样式中,由于历史兼容性的原因,零作为一个步骤(即num.steplimit,0))是不允许的。

如果所有参数都是整数,则循环使用整数计数器进行操作。

如果任何参数都是浮点数,则所有参数都转换为浮点数,并执行以下表达式:

floor(n + n*epsilon)+ 1

在哪里n是以下内容:

n = (limit - num)/step

否则,循环开始于num,使用小于(<)或大于(>)运算符来比较计数器limit,并使用+运算符自增。

如果没有给出块,则返回一个枚举器。

例如:

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, " " }

会产生:

[1, 2, 3, 4] [10, 9, 8, 7] 3 4 5 1 3 5 7 9 2.71828182845905 2.91828182845905 3.11828182845905

static VALUE num_step(int argc, VALUE *argv, VALUE from) { VALUE to, step; int desc, inf; RETURN_SIZED_ENUMERATOR(from, argc, argv, num_step_size desc = num_step_scan_args(argc, argv, &to, &step 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)) { 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 → complex Show source

以复杂形式返回值。

static VALUE numeric_to_c(VALUE self) { return rb_complex_new1(self }

to_int → integer Show source

调用子类的to_i方法来转换num为整数。

1.0.class => Float 1.0.to_int.class => Integer 1.0.to_i.class => Integer

static VALUE num_to_int(VALUE num) { return num_funcall0(num, id_to_i }

truncate(ndigits) → integer or float Show source

返回num截断为整数。

Numeric通过将其值转换为Float并调用Float#truncate来实现此目的。

static VALUE num_truncate(int argc, VALUE *argv, VALUE num) { return flo_truncate(argc, argv, rb_Float(num) }

zero? → true or false Show source

返回值true是否num为零。

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; }