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
,则返回包含numeric
and 的数组num
。否则,返回一个包含a numeric
和num
表示为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
如果num
和numeric
是相同的类型并具有相同的值。与此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
为负值)时,循环结束,其中限制
默认为无穷大。
在推荐的关键字参数样式中,可以省略step
和limit
(默认无穷大)中的一个或两个。在固定位置参数样式中,由于历史兼容性的原因,零作为一个步骤(即num.step
(limit
,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;
}