Spec-Zone.ru › Ruby 2.3

класс Bignum

Родитель:
Целое число

Объекты Bignum хранят целые числа, выходящие за пределы диапазона Fixnum. Объекты Bignum создаются автоматически, когда вычисления с целыми числами иначе переполнили бы Fixnum. Когда вычисление, включающее объекты Bignum, возвращает результат, который поместится в Fixnum, результат автоматически преобразуется.

Для целей побитовых операций и [], объект Bignum рассматривается как битовая строка бесконечной длины с представлением в дополнительном коде 2.

В то время как значения Fixnum являются немедленными, объекты Bignum таковыми не являются — присваивание и передача параметров работают со ссылками на объекты, а не с самими объектами.

Когда требуется mathn, деление Bignum улучшено, чтобы возвращать более точные значения из математических выражений.

(2**72) / ((2**70) * 3)  # => 4/3

Константы

GMP_VERSION

Версия загруженного GMP.

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

big % other → Numeric Показать исходный код
VALUE
rb_big_modulo(VALUE x, VALUE y)
{
    VALUE z;

    if (FIXNUM_P(y)) {
        y = rb_int2big(FIX2LONG(y));
    }
    else if (!RB_BIGNUM_TYPE_P(y)) {
        return rb_num_coerce_bin(x, y, '%');
    }
    bigdivmod(x, y, 0, &z);

    return bignorm(z);
}

Возвращает остаток от деления big на other. Для получения дополнительной информации см. Numeric#divmod.

big & numeric → integer Показать исходный код
VALUE
rb_big_and(VALUE x, VALUE y)
{
    VALUE z;
    BDIGIT *ds1, *ds2, *zds;
    long i, xn, yn, n1, n2;
    BDIGIT hibitsx, hibitsy;
    BDIGIT hibits1, hibits2;
    VALUE tmpv;
    BDIGIT tmph;
    long tmpn;

    if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
        return rb_num_coerce_bit(x, y, '&');
    }

    hibitsx = abs2twocomp(&x, &xn);
    if (FIXNUM_P(y)) {
        return bigand_int(x, xn, hibitsx, FIX2LONG(y));
    }
    hibitsy = abs2twocomp(&y, &yn);
    if (xn > yn) {
        tmpv = x; x = y; y = tmpv;
        tmpn = xn; xn = yn; yn = tmpn;
        tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
    }
    n1 = xn;
    n2 = yn;
    ds1 = BDIGITS(x);
    ds2 = BDIGITS(y);
    hibits1 = hibitsx;
    hibits2 = hibitsy;

    if (!hibits1)
        n2 = n1;

    z = bignew(n2, 0);
    zds = BDIGITS(z);

    for (i=0; i<n1; i++) {
        zds[i] = ds1[i] & ds2[i];
    }
    for (; i<n2; i++) {
        zds[i] = hibits1 & ds2[i];
    }
    twocomp2abs_bang(z, hibits1 && hibits2);
    RB_GC_GUARD(x);
    RB_GC_GUARD(y);
    return bignorm(z);
}

Выполняет побитовую операцию and между big и numeric.

big * other → Numeric Показать исходный код
VALUE
rb_big_mul(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        y = rb_int2big(FIX2LONG(y));
    }
    else if (RB_BIGNUM_TYPE_P(y)) {
    }
    else if (RB_FLOAT_TYPE_P(y)) {
        return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
    }
    else {
        return rb_num_coerce_bin(x, y, '*');
    }

    return bignorm(bigmul0(x, y));
}

Умножает big и other, возвращая результат.

big ** exponent → numeric Показать исходный код
VALUE
rb_big_pow(VALUE x, VALUE y)
{
    double d;
    SIGNED_VALUE yy;

  again:
    if (y == INT2FIX(0)) return INT2FIX(1);
    if (RB_FLOAT_TYPE_P(y)) {
        d = RFLOAT_VALUE(y);
        if ((!BIGNUM_SIGN(x) && !BIGZEROP(x)) && d != round(d))
            return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
    }
    else if (RB_BIGNUM_TYPE_P(y)) {
        y = bignorm(y);
        if (FIXNUM_P(y))
            goto again;
        rb_warn("in a**b, b may be too big");
        d = rb_big2dbl(y);
    }
    else if (FIXNUM_P(y)) {
        yy = FIX2LONG(y);

        if (yy < 0)
            return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
        else {
            VALUE z = 0;
            SIGNED_VALUE mask;
            const size_t xbits = rb_absint_numwords(x, 1, NULL);
            const size_t BIGLEN_LIMIT = 32*1024*1024;

            if (xbits == (size_t)-1 ||
                (xbits > BIGLEN_LIMIT) ||
                (xbits * yy > BIGLEN_LIMIT)) {
                rb_warn("in a**b, b may be too big");
                d = (double)yy;
            }
            else {
                for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
                    if (z) z = bigsq(z);
                    if (yy & mask) {
                        z = z ? bigtrunc(bigmul0(z, x)) : x;
                    }
                }
                return bignorm(z);
            }
        }
    }
    else {
        return rb_num_coerce_bin(x, y, rb_intern("**"));
    }
    return DBL2NUM(pow(rb_big2dbl(x), d));
}

Возводит big в степень exponent (которая может быть целым числом, числом с плавающей запятой или любым значением, которое можно привести к числу). Результат может быть Fixnum, Bignum или Float.

123456789 ** 2      #=> 15241578750190521
123456789 ** 1.2    #=> 5126464716.09932
123456789 ** -2     #=> (1/15241578750190521)
big + other → Numeric Показать исходный код
VALUE
rb_big_plus(VALUE x, VALUE y)
{
    long n;

    if (FIXNUM_P(y)) {
        n = FIX2LONG(y);
        if ((n > 0) != BIGNUM_SIGN(x)) {
            if (n < 0) {
                n = -n;
            }
            return bigsub_int(x, n);
        }
        if (n < 0) {
            n = -n;
        }
        return bigadd_int(x, n);
    }
    else if (RB_BIGNUM_TYPE_P(y)) {
        return bignorm(bigadd(x, y, 1));
    }
    else if (RB_FLOAT_TYPE_P(y)) {
        return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
    }
    else {
        return rb_num_coerce_bin(x, y, '+');
    }
}

Складывает big и other, возвращая результат.

big - other → Numeric Показать исходный код
VALUE
rb_big_minus(VALUE x, VALUE y)
{
    long n;

    if (FIXNUM_P(y)) {
        n = FIX2LONG(y);
        if ((n > 0) != BIGNUM_SIGN(x)) {
            if (n < 0) {
                n = -n;
            }
            return bigadd_int(x, n);
        }
        if (n < 0) {
            n = -n;
        }
        return bigsub_int(x, n);
    }
    else if (RB_BIGNUM_TYPE_P(y)) {
        return bignorm(bigadd(x, y, 0));
    }
    else if (RB_FLOAT_TYPE_P(y)) {
        return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
    }
    else {
        return rb_num_coerce_bin(x, y, '-');
    }
}

Вычитает other из big, возвращая результат.

-big → integer Показать исходный код
VALUE
rb_big_uminus(VALUE x)
{
    VALUE z = rb_big_clone(x);

    BIGNUM_SET_SIGN(z, !BIGNUM_SIGN(x));

    return bignorm(z);
}

Унарный минус (возвращает целое число, значение которого равно 0-big)

big / other → Numeric Показать исходный код
VALUE
rb_big_div(VALUE x, VALUE y)
{
    return rb_big_divide(x, y, '/');
}

Выполняет деление: класс результирующего объекта зависит от класса numeric и от величины результата.

big < real → true или false Показать исходный код
static VALUE
big_lt(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_lt);
}

Возвращает true, если значение big меньше значения real.

big << numeric → integer Показать исходный код
VALUE
rb_big_lshift(VALUE x, VALUE y)
{
    int lshift_p;
    size_t shift_numdigits;
    int shift_numbits;

    for (;;) {
        if (FIXNUM_P(y)) {
            long l = FIX2LONG(y);
            unsigned long shift;
            if (0 <= l) {
                lshift_p = 1;
                shift = l;
            }
            else {
                lshift_p = 0;
                shift = 1+(unsigned long)(-(l+1));
            }
            shift_numbits = (int)(shift & (BITSPERDIG-1));
            shift_numdigits = shift >> bit_length(BITSPERDIG-1);
            return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
        }
        else if (RB_BIGNUM_TYPE_P(y)) {
            return bignorm(big_shift2(x, 1, y));
        }
        y = rb_to_int(y);
    }
}

Сдвигает big влево на numeric позиций (вправо, если numeric отрицательно).

big <= real → true или false Показать исходный код
static VALUE
big_le(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_le);
}

Возвращает true, если значение big меньше или равно значению real.

big <=> numeric → -1, 0, +1 или nil Показать исходный код
VALUE
rb_big_cmp(VALUE x, VALUE y)
{
    int cmp;

    if (FIXNUM_P(y)) {
        x = bignorm(x);
        if (FIXNUM_P(x)) {
            if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
            if (FIX2LONG(x) < FIX2LONG(y)) return INT2FIX(-1);
            return INT2FIX(0);
        }
        else {
            if (BIGNUM_NEGATIVE_P(x)) return INT2FIX(-1);
            return INT2FIX(1);
        }
    }
    else if (RB_BIGNUM_TYPE_P(y)) {
    }
    else if (RB_FLOAT_TYPE_P(y)) {
        return rb_integer_float_cmp(x, y);
    }
    else {
        return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
    }

    if (BIGNUM_SIGN(x) > BIGNUM_SIGN(y)) return INT2FIX(1);
    if (BIGNUM_SIGN(x) < BIGNUM_SIGN(y)) return INT2FIX(-1);

    cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
    if (BIGNUM_SIGN(x))
        return INT2FIX(cmp);
    else
        return INT2FIX(-cmp);
}

Сравнение — Возвращает -1, 0 или +1 в зависимости от того, меньше ли big чем, равно ли, или больше чем numeric. Это основа для тестов в Comparable.

Возвращается nil, если два значения несравнимы.

big == obj → true или false Показать исходный код
VALUE
rb_big_eq(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (bignorm(x) == y) return Qtrue;
        y = rb_int2big(FIX2LONG(y));
    }
    else if (RB_BIGNUM_TYPE_P(y)) {
    }
    else if (RB_FLOAT_TYPE_P(y)) {
        return rb_integer_float_eq(x, y);
    }
    else {
        return rb_equal(y, x);
    }
    if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
    if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}

Возвращает true только в том случае, если obj имеет такое же значение, что и big. Противопоставьте это Bignum#eql?, которое требует, чтобы obj был Bignum.

68719476736 == 68719476736.0   #=> true
big == obj → true или false Показать исходный код
VALUE
rb_big_eq(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (bignorm(x) == y) return Qtrue;
        y = rb_int2big(FIX2LONG(y));
    }
    else if (RB_BIGNUM_TYPE_P(y)) {
    }
    else if (RB_FLOAT_TYPE_P(y)) {
        return rb_integer_float_eq(x, y);
    }
    else {
        return rb_equal(y, x);
    }
    if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
    if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}

Возвращает true только в том случае, если obj имеет такое же значение, что и big. Противопоставьте это Bignum#eql?, которое требует, чтобы obj был Bignum.

68719476736 == 68719476736.0   #=> true
big > real → true или false Показать исходный код
static VALUE
big_gt(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_gt);
}

Возвращает true, если значение big больше значения real.

big >= real → true или false Показать исходный код
static VALUE
big_ge(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_ge);
}

Возвращает true, если значение big больше или равно значению real.

big >> numeric → integer Показать исходный код
VALUE
rb_big_rshift(VALUE x, VALUE y)
{
    int lshift_p;
    size_t shift_numdigits;
    int shift_numbits;

    for (;;) {
        if (FIXNUM_P(y)) {
            long l = FIX2LONG(y);
            unsigned long shift;
            if (0 <= l) {
                lshift_p = 0;
                shift = l;
            }
            else {
                lshift_p = 1;
                shift = 1+(unsigned long)(-(l+1));
            }
            shift_numbits = (int)(shift & (BITSPERDIG-1));
            shift_numdigits = shift >> bit_length(BITSPERDIG-1);
            return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
        }
        else if (RB_BIGNUM_TYPE_P(y)) {
            return bignorm(big_shift2(x, 0, y));
        }
        y = rb_to_int(y);
    }
}

Сдвигает big вправо на numeric позиций (влево, если numeric отрицательно).

big[n] → 0 или 1 Показать исходный код
static VALUE
rb_big_aref(VALUE x, VALUE y)
{
    BDIGIT *xds;
    size_t shift;
    size_t i, s1, s2;
    long l;
    BDIGIT bit;

    if (RB_BIGNUM_TYPE_P(y)) {
        if (!BIGNUM_SIGN(y))
            return INT2FIX(0);
        bigtrunc(y);
        if (BIGSIZE(y) > sizeof(size_t)) {
          out_of_range:
            return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
        }
#if SIZEOF_SIZE_T <= SIZEOF_LONG
        shift = big2ulong(y, "long");
#else
        shift = big2ull(y, "long long");
#endif
    }
    else {
        l = NUM2LONG(y);
        if (l < 0) return INT2FIX(0);
        shift = (size_t)l;
    }
    s1 = shift/BITSPERDIG;
    s2 = shift%BITSPERDIG;
    bit = (BDIGIT)1 << s2;

    if (s1 >= BIGNUM_LEN(x)) goto out_of_range;

    xds = BDIGITS(x);
    if (BIGNUM_POSITIVE_P(x))
        return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
    if (xds[s1] & (bit-1))
        return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
    for (i = 0; i < s1; i++)
        if (xds[i])
            return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
    return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
}

Ссылка на бит — Возвращает n-й бит в (предполагаемом) двоичном представлении big, где big — наименее значимый бит.

a = 9**15
50.downto(0) do |n|
  print a[n]
end

выдает:

000101110110100000111000011110010100111100010111001
big ^ numeric → integer Показать исходный код
VALUE
rb_big_xor(VALUE x, VALUE y)
{
    VALUE z;
    BDIGIT *ds1, *ds2, *zds;
    long i, xn, yn, n1, n2;
    BDIGIT hibitsx, hibitsy;
    BDIGIT hibits1, hibits2;
    VALUE tmpv;
    BDIGIT tmph;
    long tmpn;

    if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
        return rb_num_coerce_bit(x, y, '^');
    }

    hibitsx = abs2twocomp(&x, &xn);
    if (FIXNUM_P(y)) {
        return bigxor_int(x, xn, hibitsx, FIX2LONG(y));
    }
    hibitsy = abs2twocomp(&y, &yn);
    if (xn > yn) {
        tmpv = x; x = y; y = tmpv;
        tmpn = xn; xn = yn; yn = tmpn;
        tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
    }
    n1 = xn;
    n2 = yn;
    ds1 = BDIGITS(x);
    ds2 = BDIGITS(y);
    hibits1 = hibitsx;
    hibits2 = hibitsy;

    z = bignew(n2, 0);
    zds = BDIGITS(z);

    for (i=0; i<n1; i++) {
        zds[i] = ds1[i] ^ ds2[i];
    }
    for (; i<n2; i++) {
        zds[i] = hibitsx ^ ds2[i];
    }
    twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
    RB_GC_GUARD(x);
    RB_GC_GUARD(y);
    return bignorm(z);
}

Выполняет побитовую операцию +исключающее или+ между big и numeric.

abs → aBignum Показать исходный код
static VALUE
rb_big_abs(VALUE x)
{
    if (!BIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        BIGNUM_SET_SIGN(x, 1);
    }
    return x;
}

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

-1234567890987654321.abs   #=> 1234567890987654321
bit_length → integer Показать исходный код
static VALUE
rb_big_bit_length(VALUE big)
{
    int nlz_bits;
    size_t numbytes;

    static const BDIGIT char_bit[1] = { CHAR_BIT };
    BDIGIT numbytes_bary[bdigit_roomof(sizeof(size_t))];
    BDIGIT nlz_bary[1];
    BDIGIT result_bary[bdigit_roomof(sizeof(size_t)+1)];

    numbytes = rb_absint_size(big, &nlz_bits);

    if (numbytes == 0)
        return LONG2FIX(0);

    if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
        if (nlz_bits != CHAR_BIT-1) {
            nlz_bits++;
        }
        else {
            nlz_bits = 0;
            numbytes--;
        }
    }

    if (numbytes <= SIZE_MAX / CHAR_BIT) {
        return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
    }

    nlz_bary[0] = nlz_bits;

    bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
            INTEGER_PACK_NATIVE_BYTE_ORDER);
    BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
    BARY_SUB(result_bary, result_bary, nlz_bary);

    return rb_integer_unpack(result_bary, numberof(result_bary), sizeof(BDIGIT), 0,
            INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
}

Возвращает количество битов значения int.

«Количество битов» означает позицию бита самого старшего бита, отличного от знака. (Позиция бита 2**n равна n+1). Если такого бита нет (ноль или минус один), возвращается ноль.

Т.е. Этот метод возвращает ceil(log2(int < 0 ? -int : int+1)).

(-2**10000-1).bit_length  #=> 10001
(-2**10000).bit_length    #=> 10000
(-2**10000+1).bit_length  #=> 10000

(-2**1000-1).bit_length   #=> 1001
(-2**1000).bit_length     #=> 1000
(-2**1000+1).bit_length   #=> 1000

(2**1000-1).bit_length    #=> 1000
(2**1000).bit_length      #=> 1001
(2**1000+1).bit_length    #=> 1001

(2**10000-1).bit_length   #=> 10000
(2**10000).bit_length     #=> 10001
(2**10000+1).bit_length   #=> 10001

Этот метод может быть использован для обнаружения переполнения в Array#pack следующим образом.

if n.bit_length < 32
  [n].pack("l") # no overflow
else
  raise "overflow"
end
coerce(numeric) → массив Показать исходный код
static VALUE
rb_big_coerce(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        y = rb_int2big(FIX2LONG(y));
    }
    else if (!RB_BIGNUM_TYPE_P(y)) {
        rb_raise(rb_eTypeError, "can't coerce %"PRIsVALUE" to Bignum",
                 rb_obj_class(y));
    }
    return rb_assoc_new(y, x);
}

Возвращает массив, содержащий как numeric, так и big, представленные как объекты Bignum.

Это достигается путем преобразования numeric в Bignum.

Если numeric не является типом Fixnum или Bignum, генерируется TypeError.

(0x3FFFFFFFFFFFFFFF+1).coerce(42)   #=> [42, 4611686018427387904]
div(other) → integer Показать исходный код
VALUE
rb_big_idiv(VALUE x, VALUE y)
{
    return rb_big_divide(x, y, rb_intern("div"));
}

Выполняет целочисленное деление: возвращает целое значение.

divmod(numeric) → массив Показать исходный код
VALUE
rb_big_divmod(VALUE x, VALUE y)
{
    VALUE div, mod;

    if (FIXNUM_P(y)) {
        y = rb_int2big(FIX2LONG(y));
    }
    else if (!RB_BIGNUM_TYPE_P(y)) {
        return rb_num_coerce_bin(x, y, rb_intern("divmod"));
    }
    bigdivmod(x, y, &div, &mod);

    return rb_assoc_new(bignorm(div), bignorm(mod));
}

См. Numeric#divmod.

eql?(obj) → true or false Показать исходный код
VALUE
rb_big_eql(VALUE x, VALUE y)
{
    if (!RB_BIGNUM_TYPE_P(y)) return Qfalse;
    if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
    if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}

Возвращает true только в том случае, если obj является объектом с тем же значением, что и big. В отличие от этого, Bignum#==, который выполняет преобразования типов.

68719476736.eql?(68719476736.0)   #=> false
even? → true or false Показать исходный код
static VALUE
rb_big_even_p(VALUE num)
{
    if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
        return Qfalse;
    }
    return Qtrue;
}

Возвращает true, если big является чётным числом.

fdiv(numeric) → float Показать исходный код
VALUE
rb_big_fdiv(VALUE x, VALUE y)
{
    double dx, dy;

    dx = big2dbl(x);
    if (FIXNUM_P(y)) {
        dy = (double)FIX2LONG(y);
        if (isinf(dx))
            return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
    }
    else if (RB_BIGNUM_TYPE_P(y)) {
        dy = rb_big2dbl(y);
        if (isinf(dx) || isinf(dy))
            return big_fdiv_int(x, y);
    }
    else if (RB_FLOAT_TYPE_P(y)) {
        dy = RFLOAT_VALUE(y);
        if (isnan(dy))
            return y;
        if (isinf(dx))
            return big_fdiv_float(x, y);
    }
    else {
        return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
    }
    return DBL2NUM(dx / dy);
}

Возвращает результат деления big на numeric с плавающей точкой.

-1234567890987654321.fdiv(13731)      #=> -89910996357705.5
-1234567890987654321.fdiv(13731.24)   #=> -89909424858035.7
hash → fixnum Показать исходный код
VALUE
rb_big_hash(VALUE x)
{
    st_index_t hash;

    hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
    return INT2FIX(hash);
}

Вычисляет хэш на основе значения big.

См. также Object#hash.

inspect(p1 = v1)
Псевдоним для: to_s
magnitude → aBignum Показать исходный код
static VALUE
rb_big_abs(VALUE x)
{
    if (!BIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        BIGNUM_SET_SIGN(x, 1);
    }
    return x;
}

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

-1234567890987654321.abs   #=> 1234567890987654321
modulo(other) → Numeric Показать исходный код
VALUE
rb_big_modulo(VALUE x, VALUE y)
{
    VALUE z;

    if (FIXNUM_P(y)) {
        y = rb_int2big(FIX2LONG(y));
    }
    else if (!RB_BIGNUM_TYPE_P(y)) {
        return rb_num_coerce_bin(x, y, '%');
    }
    bigdivmod(x, y, 0, &z);

    return bignorm(z);
}

Возвращает остаток от деления big на other. Смотрите Numeric#divmod для получения дополнительной информации.

odd? → true or false Показать исходный код
static VALUE
rb_big_odd_p(VALUE num)
{
    if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
        return Qtrue;
    }
    return Qfalse;
}

Возвращает true, если big является нечётным числом.

remainder(numeric) → number Показать исходный код
static VALUE
rb_big_remainder(VALUE x, VALUE y)
{
    VALUE z;

    if (FIXNUM_P(y)) {
        y = rb_int2big(FIX2LONG(y));
    }
    else if (!RB_BIGNUM_TYPE_P(y)) {
        return rb_num_coerce_bin(x, y, rb_intern("remainder"));
    }
    bigdivrem(x, y, 0, &z);

    return bignorm(z);
}

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

-1234567890987654321.remainder(13731)      #=> -6966
-1234567890987654321.remainder(13731.24)   #=> -9906.22531493148
size → integer Показать исходный код
static VALUE
rb_big_size(VALUE big)
{
    return SIZET2NUM(BIGSIZE(big));
}

Возвращает количество байтов в машинном представлении big.

(256**10 - 1).size   #=> 12
(256**20 - 1).size   #=> 20
(256**40 - 1).size   #=> 40
to_f → float Показать исходный код
static VALUE
rb_big_to_f(VALUE x)
{
    return DBL2NUM(rb_big2dbl(x));
}

Преобразует big в число с плавающей точкой. Если big не помещается в число с плавающей точкой, результат — бесконечность.

to_s(base=10) → string Показать исходный код
static VALUE
rb_big_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_big2str(x, base);
}

Возвращает строку, содержащую представление big в системе счисления с основанием base (от 2 до 36).

12345654321.to_s         #=> "12345654321"
12345654321.to_s(2)      #=> "1011011111110110111011110000110001"
12345654321.to_s(8)      #=> "133766736061"
12345654321.to_s(16)     #=> "2dfdbbc31"
78546939656932.to_s(36)  #=> "rubyrules"
Также алиас: inspect
big | numeric → integer Показать исходный код
VALUE
rb_big_or(VALUE x, VALUE y)
{
    VALUE z;
    BDIGIT *ds1, *ds2, *zds;
    long i, xn, yn, n1, n2;
    BDIGIT hibitsx, hibitsy;
    BDIGIT hibits1, hibits2;
    VALUE tmpv;
    BDIGIT tmph;
    long tmpn;

    if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
        return rb_num_coerce_bit(x, y, '|');
    }

    hibitsx = abs2twocomp(&x, &xn);
    if (FIXNUM_P(y)) {
        return bigor_int(x, xn, hibitsx, FIX2LONG(y));
    }
    hibitsy = abs2twocomp(&y, &yn);
    if (xn > yn) {
        tmpv = x; x = y; y = tmpv;
        tmpn = xn; xn = yn; yn = tmpn;
        tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
    }
    n1 = xn;
    n2 = yn;
    ds1 = BDIGITS(x);
    ds2 = BDIGITS(y);
    hibits1 = hibitsx;
    hibits2 = hibitsy;

    if (hibits1)
        n2 = n1;

    z = bignew(n2, 0);
    zds = BDIGITS(z);

    for (i=0; i<n1; i++) {
        zds[i] = ds1[i] | ds2[i];
    }
    for (; i<n2; i++) {
        zds[i] = hibits1 | ds2[i];
    }
    twocomp2abs_bang(z, hibits1 || hibits2);
    RB_GC_GUARD(x);
    RB_GC_GUARD(y);
    return bignorm(z);
}

Выполняет побитовое or между big и numeric.

~big → integer Показать исходный код
static VALUE
rb_big_neg(VALUE x)
{
    VALUE z = rb_big_clone(x);
    BDIGIT *ds = BDIGITS(z);
    long n = BIGNUM_LEN(z);

    if (!n) return INT2FIX(-1);

    if (BIGNUM_POSITIVE_P(z)) {
        if (bary_add_one(ds, n)) {
            big_extend_carry(z);
        }
        BIGNUM_SET_NEGATIVE_SIGN(z);
    }
    else {
        bary_neg(ds, n);
        if (bary_add_one(ds, n))
            return INT2FIX(-1);
        bary_neg(ds, n);
        BIGNUM_SET_POSITIVE_SIGN(z);
    }

    return bignorm(z);
}

Инвертирует биты в big. Поскольку Bignums концептуально имеют бесконечную длину, результат ведет себя так, как если бы у него было бесконечное число единичных битов слева. В шестнадцатеричном представлении это отображается как две точки слева от цифр.

sprintf("%X", ~0x1122334455)    #=> "..FEEDDCCBBAA"

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

Spec-Zone.ru

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