класс Fixnum
При необходимости в математических вычислениях, деление Fixnum улучшено, чтобы возвращать более точные значения.
2/3*3 # => 0 require 'mathn' 2/3*3 # => 2
Содержит значения целых чисел, которые могут быть представлены в машинном слове (минус 1 бит). Если любая операция над Fixnum превышает этот диапазон, значение автоматически преобразуется в большое целое число.
Объекты Fixnum имеют непосредственное значение. Это означает, что при присваивании или передаче в качестве параметров передается фактический объект, а не ссылка на этот объект.
Присваивание не создаёт псевдонимы для объектов Fixnum. Для каждого целого значения существует фактически только один экземпляр объекта Fixnum, поэтому, например, нельзя добавить метод singleton к Fixnum. Любая попытка добавить метод singleton к объекту Fixnum вызовет исключение TypeError.
Общедоступные методы экземпляров
static VALUE
fix_mod(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
long mod;
fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
return LONG2NUM(mod);
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
x = rb_int2big(FIX2LONG(x));
return rb_big_modulo(x, y);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return DBL2NUM(ruby_float_mod((double)FIX2LONG(x), RFLOAT_VALUE(y)));
}
else {
return rb_num_coerce_bin(x, y, '%');
}
} Возвращает остаток от деления fix на other.
См. Numeric#divmod для получения дополнительной информации.
static VALUE
fix_and(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
long val = FIX2LONG(x) & FIX2LONG(y);
return LONG2NUM(val);
}
if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_and(y, x);
}
bit_coerce(&x, &y);
return rb_funcall(x, rb_intern("&"), 1, y);
} Побитовое И.
static VALUE
fix_mul(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
#ifdef __HP_cc
/* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
volatile
#endif
long a, b;
#if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
LONG_LONG d;
#else
VALUE r;
#endif
a = FIX2LONG(x);
b = FIX2LONG(y);
#if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
d = (LONG_LONG)a * b;
if (FIXABLE(d)) return LONG2FIX(d);
return rb_ll2inum(d);
#else
if (a == 0) return x;
if (MUL_OVERFLOW_FIXNUM_P(a, b))
r = rb_big_mul(rb_int2big(a), rb_int2big(b));
else
r = LONG2FIX(a * b);
return r;
#endif
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_mul(y, x);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return DBL2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
}
else {
return rb_num_coerce_bin(x, y, '*');
}
} Выполняет умножение: класс результирующего объекта зависит от класса numeric и от величины результата. Может возвращать Bignum.
static VALUE
fix_pow(VALUE x, VALUE y)
{
long a = FIX2LONG(x);
if (FIXNUM_P(y)) {
long b = FIX2LONG(y);
if (a == 1) return INT2FIX(1);
if (a == -1) {
if (b % 2 == 0)
return INT2FIX(1);
else
return INT2FIX(-1);
}
if (b < 0)
return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
if (b == 0) return INT2FIX(1);
if (b == 1) return x;
if (a == 0) {
if (b > 0) return INT2FIX(0);
return DBL2NUM(INFINITY);
}
return int_pow(a, b);
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
if (a == 1) return INT2FIX(1);
if (a == -1) {
if (int_even_p(y)) return INT2FIX(1);
else return INT2FIX(-1);
}
if (negative_int_p(y))
return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
if (a == 0) return INT2FIX(0);
x = rb_int2big(FIX2LONG(x));
return rb_big_pow(x, y);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
if (RFLOAT_VALUE(y) == 0.0) return DBL2NUM(1.0);
if (a == 0) {
return DBL2NUM(RFLOAT_VALUE(y) < 0 ? INFINITY : 0.0);
}
if (a == 1) return DBL2NUM(1.0);
{
double dy = RFLOAT_VALUE(y);
if (a < 0 && dy != round(dy))
return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
return DBL2NUM(pow((double)a, dy));
}
}
else {
return rb_num_coerce_bin(x, y, rb_intern("**"));
}
} Возводит fix в степень numeric, которая может быть отрицательной или дробной.
2 ** 3 #=> 8 2 ** -1 #=> (1/2) 2 ** 0.5 #=> 1.4142135623731
static VALUE
fix_plus(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
long a, b, c;
VALUE r;
a = FIX2LONG(x);
b = FIX2LONG(y);
c = a + b;
r = LONG2NUM(c);
return r;
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_plus(y, x);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
}
else {
return rb_num_coerce_bin(x, y, '+');
}
} Выполняет сложение: класс результирующего объекта зависит от класса numeric и от величины результата. Может возвращать Bignum.
static VALUE
fix_minus(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
long a, b, c;
VALUE r;
a = FIX2LONG(x);
b = FIX2LONG(y);
c = a - b;
r = LONG2NUM(c);
return r;
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
x = rb_int2big(FIX2LONG(x));
return rb_big_minus(x, y);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
}
else {
return rb_num_coerce_bin(x, y, '-');
}
} Выполняет вычитание: класс результирующего объекта зависит от класса numeric и от величины результата. Может возвращать Bignum.
static VALUE
fix_uminus(VALUE num)
{
return LONG2NUM(-FIX2LONG(num));
} Изменяет знак fix, что может возвращать Bignum.
static VALUE
fix_div(VALUE x, VALUE y)
{
return fix_divide(x, y, '/');
} Выполняет деление: класс результирующего объекта зависит от класса numeric и от величины результата. Может возвращать Bignum.
static VALUE
fix_lt(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
if (FIX2LONG(x) < FIX2LONG(y)) return Qtrue;
return Qfalse;
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse;
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return rb_integer_float_cmp(x, y) == INT2FIX(-1) ? Qtrue : Qfalse;
}
else {
return rb_num_coerce_relop(x, y, '<');
}
} Возвращает true, если значение fix меньше значения real.
static VALUE
rb_fix_lshift(VALUE x, VALUE y)
{
long val, width;
val = NUM2LONG(x);
if (!FIXNUM_P(y))
return rb_big_lshift(rb_int2big(val), y);
width = FIX2LONG(y);
if (width < 0)
return fix_rshift(val, (unsigned long)-width);
return fix_lshift(val, width);
} Сдвигает fix влево на count позиций или вправо, если count отрицательно.
static VALUE
fix_le(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
if (FIX2LONG(x) <= FIX2LONG(y)) return Qtrue;
return Qfalse;
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse;
}
else if (RB_TYPE_P(y, T_FLOAT)) {
VALUE rel = rb_integer_float_cmp(x, y);
return rel == INT2FIX(-1) || rel == INT2FIX(0) ? Qtrue : Qfalse;
}
else {
return rb_num_coerce_relop(x, y, rb_intern("<="));
}
} Возвращает true, если значение fix меньше или равно значению real.
static VALUE
fix_cmp(VALUE x, VALUE y)
{
if (x == y) return INT2FIX(0);
if (FIXNUM_P(y)) {
if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
return INT2FIX(-1);
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_cmp(rb_int2big(FIX2LONG(x)), y);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return rb_integer_float_cmp(x, y);
}
else {
return rb_num_coerce_cmp(x, y, id_cmp);
}
} Сравнение — возвращает -1, 0, +1 или nil в зависимости от того, меньше ли, равно ли или больше ли fix значения numeric.
Возвращает nil, если два значения несравнимы.
static VALUE
fix_equal(VALUE x, VALUE y)
{
if (x == y) return Qtrue;
if (FIXNUM_P(y)) return Qfalse;
else if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_eq(y, x);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return rb_integer_float_eq(x, y);
}
else {
return num_equal(x, y);
}
} Возвращает true, если fix численно равно other.
1 == 2 #=> false 1 == 1.0 #=> true
static VALUE
fix_equal(VALUE x, VALUE y)
{
if (x == y) return Qtrue;
if (FIXNUM_P(y)) return Qfalse;
else if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_eq(y, x);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return rb_integer_float_eq(x, y);
}
else {
return num_equal(x, y);
}
} Возвращает true, если fix численно равно other.
1 == 2 #=> false 1 == 1.0 #=> true
static VALUE
fix_gt(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
if (FIX2LONG(x) > FIX2LONG(y)) return Qtrue;
return Qfalse;
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse;
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return rb_integer_float_cmp(x, y) == INT2FIX(1) ? Qtrue : Qfalse;
}
else {
return rb_num_coerce_relop(x, y, '>');
}
} Возвращает true, если значение fix больше значения real.
static VALUE
fix_ge(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue;
return Qfalse;
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse;
}
else if (RB_TYPE_P(y, T_FLOAT)) {
VALUE rel = rb_integer_float_cmp(x, y);
return rel == INT2FIX(1) || rel == INT2FIX(0) ? Qtrue : Qfalse;
}
else {
return rb_num_coerce_relop(x, y, rb_intern(">="));
}
} Возвращает true, если значение fix больше или равно значению real.
static VALUE
rb_fix_rshift(VALUE x, VALUE y)
{
long i, val;
val = FIX2LONG(x);
if (!FIXNUM_P(y))
return rb_big_rshift(rb_int2big(val), y);
i = FIX2LONG(y);
if (i == 0) return x;
if (i < 0)
return fix_lshift(val, (unsigned long)-i);
return fix_rshift(val, i);
} Сдвигает fix вправо на count позиций или влево, если count отрицательно.
static VALUE
fix_aref(VALUE fix, VALUE idx)
{
long val = FIX2LONG(fix);
long i;
idx = rb_to_int(idx);
if (!FIXNUM_P(idx)) {
idx = rb_big_norm(idx);
if (!FIXNUM_P(idx)) {
if (!BIGNUM_SIGN(idx) || val >= 0)
return INT2FIX(0);
return INT2FIX(1);
}
}
i = FIX2LONG(idx);
if (i < 0) return INT2FIX(0);
if (SIZEOF_LONG*CHAR_BIT-1 <= i) {
if (val < 0) return INT2FIX(1);
return INT2FIX(0);
}
if (val & (1L<<i))
return INT2FIX(1);
return INT2FIX(0);
} Ссылка на бит — возвращает +n+‑й бит в двоичном представлении fix, где fix[0] — наименее значащий бит.
Например:
a = 0b11001100101010 30.downto(0) do |n| print a[n] end #=> 0000000000000000011001100101010
static VALUE
fix_xor(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
long val = FIX2LONG(x) ^ FIX2LONG(y);
return LONG2NUM(val);
}
if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_xor(y, x);
}
bit_coerce(&x, &y);
return rb_funcall(x, rb_intern("^"), 1, y);
} Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ.
static VALUE
fix_abs(VALUE fix)
{
long i = FIX2LONG(fix);
if (i < 0) i = -i;
return LONG2NUM(i);
} Возвращает абсолютное значение fix.
-12345.abs #=> 12345 12345.abs #=> 12345
static VALUE
rb_fix_bit_length(VALUE fix)
{
long v = FIX2LONG(fix);
if (v < 0)
v = ~v;
return LONG2FIX(bit_length(v));
} Возвращает количество битов значения int.
«Количество битов» означает позицию бита самого старшего бита, отличного от знакового бита. (Позиция бита 2**n равна n+1.) Если такого бита нет (ноль или минус один), возвращается ноль.
Т.е. этот метод возвращает ceil(log2(int < 0 ? -int : int+1)).
(-2**12-1).bit_length #=> 13 (-2**12).bit_length #=> 12 (-2**12+1).bit_length #=> 12 -0x101.bit_length #=> 9 -0x100.bit_length #=> 8 -0xff.bit_length #=> 8 -2.bit_length #=> 1 -1.bit_length #=> 0 0.bit_length #=> 0 1.bit_length #=> 1 0xff.bit_length #=> 8 0x100.bit_length #=> 9 (2**12-1).bit_length #=> 12 (2**12).bit_length #=> 13 (2**12+1).bit_length #=> 13
Этот метод может использоваться для обнаружения переполнения в Array#pack следующим образом.
if n.bit_length < 32
[n].pack("l") # no overflow
else
raise "overflow"
end
# File lib/rexml/xpath_parser.rb, line 22 def dclone ; self ; end
предоставляет унифицированную clone операцию для REXML::XPathParser для использования с различными типами Object
static VALUE
fix_idiv(VALUE x, VALUE y)
{
return fix_divide(x, y, rb_intern("div"));
} Выполняет целочисленное деление: возвращает целое число, полученное при делении fix на numeric.
static VALUE
fix_divmod(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
long div, mod;
fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
x = rb_int2big(FIX2LONG(x));
return rb_big_divmod(x, y);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
{
double div, mod;
volatile VALUE a, b;
flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), &div, &mod);
a = dbl2ival(div);
b = DBL2NUM(mod);
return rb_assoc_new(a, b);
}
}
else {
return rb_num_coerce_bin(x, y, rb_intern("divmod"));
}
} См. Numeric#divmod.
static VALUE
fix_even_p(VALUE num)
{
if (num & 2) {
return Qfalse;
}
return Qtrue;
} Возвращает true , если fix является чётным числом.
static VALUE
fix_fdiv(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
return DBL2NUM((double)FIX2LONG(x) / (double)FIX2LONG(y));
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_fdiv(rb_int2big(FIX2LONG(x)), y);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return DBL2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y));
}
else {
return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
}
} Возвращает результат деления с плавающей точкой fix на numeric.
654321.fdiv(13731) #=> 47.6528293642124 654321.fdiv(13731.24) #=> 47.6519964693647
static VALUE
fix_abs(VALUE fix)
{
long i = FIX2LONG(fix);
if (i < 0) i = -i;
return LONG2NUM(i);
} Возвращает абсолютное значение fix.
-12345.abs #=> 12345 12345.abs #=> 12345
static VALUE
fix_mod(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
long mod;
fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
return LONG2NUM(mod);
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
x = rb_int2big(FIX2LONG(x));
return rb_big_modulo(x, y);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
return DBL2NUM(ruby_float_mod((double)FIX2LONG(x), RFLOAT_VALUE(y)));
}
else {
return rb_num_coerce_bin(x, y, '%');
}
} Возвращает fix по модулю other.
См. Numeric#divmod для получения дополнительной информации.
static VALUE
fix_odd_p(VALUE num)
{
if (num & 2) {
return Qtrue;
}
return Qfalse;
} Возвращает true , если fix является нечётным числом.
static VALUE
fix_size(VALUE fix)
{
return INT2FIX(sizeof(long));
} Возвращает количество байтов в машинном представлении fix.
1.size #=> 4 -1.size #=> 4 2147483647.size #=> 4
static VALUE
fix_succ(VALUE num)
{
long i = FIX2LONG(num) + 1;
return LONG2NUM(i);
} Возвращает целое число , равное int + 1.
1.next #=> 2 (-1).next #=> 0
static VALUE
fix_to_f(VALUE num)
{
double val;
val = (double)FIX2LONG(num);
return DBL2NUM(val);
} Преобразует fix в float.
static VALUE
fix_to_s(int argc, VALUE *argv, VALUE x)
{
int base;
if (argc == 0) base = 10;
else {
VALUE b;
rb_scan_args(argc, argv, "01", &b);
base = NUM2INT(b);
}
return rb_fix2str(x, base);
} Возвращает строку, содержащую представление fix в системе счисления с основанием base (от 2 до 36).
12345.to_s #=> "12345" 12345.to_s(2) #=> "11000000111001" 12345.to_s(8) #=> "30071" 12345.to_s(10) #=> "12345" 12345.to_s(16) #=> "3039" 12345.to_s(36) #=> "9ix"
static VALUE
fix_zero_p(VALUE num)
{
if (FIX2LONG(num) == 0) {
return Qtrue;
}
return Qfalse;
} Возвращает true , если fix равно нулю.
static VALUE
fix_or(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
long val = FIX2LONG(x) | FIX2LONG(y);
return LONG2NUM(val);
}
if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_or(y, x);
}
bit_coerce(&x, &y);
return rb_funcall(x, rb_intern("|"), 1, y);
} Побитовое ИЛИ.
static VALUE
fix_rev(VALUE num)
{
return ~num | FIXNUM_FLAG;
} Инверсия: возвращает число, где каждый бит инвертирован.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.