Spec-Zone.ru › Ruby 3.3

класс BigDecimal

Родитель:
Numeric

BigDecimal предоставляет арифметику с плавающей точкой и произвольной точностью для десятичных чисел.

Введение

Ruby предоставляет встроенную поддержку арифметики с целыми числами произвольной точности.

Например:

42**13  #=>   1265437718438866624512

BigDecimal предоставляет аналогичную поддержку для очень больших или очень точных чисел с плавающей точкой.

Десятичная арифметика также полезна для общих вычислений, потому что она дает правильные ответы, ожидаемые пользователями, в то время как обычная двоичная арифметика с плавающей точкой часто вносит незначительные ошибки из-за преобразования между системами счисления с основанием 10 и 2.

Например, попробуйте:

sum = 0
10_000.times do
  sum = sum + 0.0001
end
print sum #=> 0.9999999999999062

и сравните с результатом:

require 'bigdecimal'

sum = BigDecimal("0")
10_000.times do
  sum = sum + BigDecimal("0.0001")
end
print sum #=> 0.1E1

Аналогично:

(BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true

(1.2 - 1.0) == 0.2 #=> false

Примечание о точности

Для вычисления с использованием BigDecimal и другого value, точность результата зависит от типа value:

  • Если value является Float, точность составляет Float::DIG + 1.

  • Если value является Rational, точность больше, чем Float::DIG + 1.

  • Если value является BigDecimal, точность составляет точность value во внутренней форме представления, которая зависит от платформы.

  • Если value это другой объект, точность определяется результатом +BigDecimal(value)+.

Особенности точной десятичной арифметики

Поскольку BigDecimal более точна, чем обычная двоичная арифметика с плавающей точкой, она требует некоторых специальных значений.

Бесконечность

BigDecimal иногда необходимо возвращать бесконечность, например, если вы делите значение на ноль.

BigDecimal("1.0") / BigDecimal("0.0")  #=> Infinity
BigDecimal("-1.0") / BigDecimal("0.0")  #=> -Infinity

Вы можете представить бесконечные числа для BigDecimal с помощью строк 'Infinity', '+Infinity' и '-Infinity' (регистр важен).

Не число (NaN)

Когда вычисление приводит к неопределённому значению, возвращается специальное значение NaN (для «не числа»).

Пример:

BigDecimal("0.0") / BigDecimal("0.0") #=> NaN

Вы также можете создать неопределённые значения.

NaN никогда не считается равным никакому другому значению, даже самому себе:

n = BigDecimal('NaN')
n == 0.0 #=> false
n == n #=> false

Положительный и отрицательный ноль

Если вычисление приводит к значению, которое слишком мало, чтобы быть представленным как BigDecimal в текущих заданных пределах точности, возвращается ноль.

Если значение, которое слишком мало для представления, отрицательно, возвращается значение отрицательного нуля BigDecimal.

BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0

Если значение положительно, возвращается значение положительного нуля.

BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0

(См. BigDecimal.mode о том, как задать пределы точности.)

Обратите внимание, что -0.0 и 0.0 считаются одинаковыми для сравнения.

Также обратите внимание, что в математике нет особого понятия отрицательного или положительного нуля; истинное математическое нуль не имеет знака.

bigdecimal/util

Когда вам требуется bigdecimal/util, метод to_d будет доступен для BigDecimal и для встроенных классов Integer, Float, Rational и String:

require 'bigdecimal/util'

42.to_d         # => 0.42e2
0.5.to_d        # => 0.5e0
(2/3r).to_d(3)  # => 0.667e0
"0.5".to_d      # => 0.5e0

Методы для работы с JSON

  • ::json_create: Возвращает новый объект BigDecimal, созданный из данного объекта.

  • #as_json: Возвращает хеш из 2 элементов, представляющий self.

  • #to_json: Возвращает строку JSON, представляющую self.

Эти методы предоставляются драгоценностью JSON. Чтобы сделать эти методы доступными:

require 'json/add/bigdecimal'
  • Лицензия

Авторское право © 2002 Шигео Кобаяси <shigeo@tinyforest.gr.jp>.

BigDecimal распространяется под лицензиями Ruby и 2-х пунктов BSD. Подробности см. в файле LICENSE.txt.

Поддерживается mrkn <mrkn@mrkn.jp> и членами ruby-core.

Документировано zzak <zachary@zacharyscott.net>, mathew <meta@pobox.com> и многими другими участниками.

Константы

BASE

Значение основания, используемое во внутренних вычислениях. На 32-битной системе BASE равно 10000, что указывает на то, что вычисления выполняются группами по 4 цифры. (Если бы оно было больше, BASE**2 не поместилось бы в 32 бита, поэтому вы не могли гарантировать, что две группы всегда могли бы быть перемножены без переполнения.)

EXCEPTION_ALL

Определяет, будут ли переполнение, недополнение или деление на ноль приводить к выбрасыванию исключения. См. BigDecimal.mode.

EXCEPTION_INFINITY

Определяет, что произойдёт, когда результат вычисления равен бесконечности. См. BigDecimal.mode.

EXCEPTION_NaN

Определяет, что произойдёт, когда результат вычисления — не число (NaN). См. BigDecimal.mode.

EXCEPTION_OVERFLOW

Определяет, что произойдёт, когда результат вычисления — переполнение (результат слишком большой для представления). См. BigDecimal.mode.

EXCEPTION_UNDERFLOW

Определяет, что произойдёт, когда результат вычисления — недополнение (результат слишком мал для представления). См. BigDecimal.mode.

EXCEPTION_ZERODIVIDE

Определяет, что произойдёт при делении на ноль. См. BigDecimal.mode.

INFINITY

Специальные константы значений

NAN
ROUND_CEILING

Округление вверх до +Бесконечности. См. BigDecimal.mode.

ROUND_DOWN

Указывает, что значения должны быть округлены к нулю. См. BigDecimal.mode.

ROUND_FLOOR

Округление вниз до -Бесконечности. См. BigDecimal.mode.

ROUND_HALF_DOWN

Указывает, что цифры >= 6 должны быть округлены вверх, а остальные — вниз. См. BigDecimal.mode.

ROUND_HALF_EVEN

Округление к ближайшему чётному соседу. См. BigDecimal.mode.

ROUND_HALF_UP

Указывает, что цифры >= 5 должны быть округлены вверх, а остальные — вниз. См. BigDecimal.mode.

ROUND_MODE

Определяет, что произойдёт, когда результат необходимо округлить, чтобы он поместился в нужное количество значащих цифр. См. BigDecimal.mode.

ROUND_UP

Указывает, что значения должны быть округлены от нуля. См. BigDecimal.mode.

SIGN_NEGATIVE_FINITE

Указывает, что значение отрицательное и конечное. См. BigDecimal.sign.

SIGN_NEGATIVE_INFINITE

Указывает, что значение отрицательное и бесконечное. См. BigDecimal.sign.

SIGN_NEGATIVE_ZERO

Указывает, что значение равно -0. См. BigDecimal.sign.

SIGN_NaN

Указывает, что значение — не число. См. BigDecimal.sign.

SIGN_POSITIVE_FINITE

Указывает, что значение положительное и конечное. См. BigDecimal.sign.

SIGN_POSITIVE_INFINITE

Указывает, что значение положительное и бесконечное. См. BigDecimal.sign.

SIGN_POSITIVE_ZERO

Указывает, что значение равно +0. См. BigDecimal.sign.

VERSION

Версия библиотеки bigdecimal

Методы публичного класса

_load(p1) Показать исходный код
static VALUE
BigDecimal_load(VALUE self, VALUE str)
{
    ENTER(2);
    Real *pv;
    unsigned char *pch;
    unsigned char ch;
    unsigned long m=0;

    pch = (unsigned char *)StringValueCStr(str);
    /* First get max prec */
    while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
        if(!ISDIGIT(ch)) {
            rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string");
        }
        m = m*10 + (unsigned long)(ch-'0');
    }
    if (m > VpBaseFig()) m -= VpBaseFig();
    GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true));
    m /= VpBaseFig();
    if (m && pv->MaxPrec > m) {
        pv->MaxPrec = m+1;
    }
    return VpCheckGetValue(pv);
}

Внутренний метод, используемый для поддержки маршалинга. Смотрите модуль Marshal.

double_fig → integer Показать исходный код
static inline VALUE
BigDecimal_double_fig(VALUE self)
{
    return INT2FIX(VpDblFig());
}

Возвращает количество цифр, которое может иметь объект Float; результат зависит от системы:

BigDecimal.double_fig # => 16
interpret_loosely(p1) Показать исходный код
static VALUE
BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
{
    char const *c_str = StringValueCStr(str);
    Real *vp = VpNewRbClass(0, c_str, klass, false, true);
    if (!vp)
        return Qnil;
    else
        return VpCheckGetValue(vp);
}
json_create(object) Показать исходный код
# File ext/json/lib/json/add/bigdecimal.rb, line 13
def self.json_create(object)
  BigDecimal._load object['b']
end

См. as_json.

limit(digits) Показать исходный код
static VALUE
BigDecimal_limit(int argc, VALUE *argv, VALUE self)
{
    VALUE  nFig;
    VALUE  nCur = SIZET2NUM(VpGetPrecLimit());

    if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
        int nf;
        if (NIL_P(nFig)) return nCur;
        nf = NUM2INT(nFig);
        if (nf < 0) {
            rb_raise(rb_eArgError, "argument must be positive");
        }
        VpSetPrecLimit(nf);
    }
    return nCur;
}

Ограничить количество значащих цифр в вновь созданных числах BigDecimal указанным значением. Округление выполняется при необходимости, согласно BigDecimal.mode.

Предел 0, по умолчанию, означает отсутствие верхнего предела.

Установленный этим методом предел имеет меньший приоритет, чем любой предел, указанный для методов экземпляров, таких как ceil, floor, truncate или round.

mode(mode, setting = nil) → integer Показать исходный код
static VALUE
BigDecimal_mode(int argc, VALUE *argv, VALUE self)
{
    VALUE which;
    VALUE val;
    unsigned long f,fo;

    rb_scan_args(argc, argv, "11", &which, &val);
    f = (unsigned long)NUM2INT(which);

    if (f & VP_EXCEPTION_ALL) {
        /* Exception mode setting */
        fo = VpGetException();
        if (val == Qnil) return INT2FIX(fo);
        if (val != Qfalse && val!=Qtrue) {
            rb_raise(rb_eArgError, "second argument must be true or false");
            return Qnil; /* Not reached */
        }
        if (f & VP_EXCEPTION_INFINITY) {
            VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_INFINITY) :
                        (fo & (~VP_EXCEPTION_INFINITY))));
        }
        fo = VpGetException();
        if (f & VP_EXCEPTION_NaN) {
            VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_NaN) :
                        (fo & (~VP_EXCEPTION_NaN))));
        }
        fo = VpGetException();
        if (f & VP_EXCEPTION_UNDERFLOW) {
            VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) :
                        (fo & (~VP_EXCEPTION_UNDERFLOW))));
        }
        fo = VpGetException();
        if(f & VP_EXCEPTION_ZERODIVIDE) {
            VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) :
                        (fo & (~VP_EXCEPTION_ZERODIVIDE))));
        }
        fo = VpGetException();
        return INT2FIX(fo);
    }
    if (VP_ROUND_MODE == f) {
        /* Rounding mode setting */
        unsigned short sw;
        fo = VpGetRoundMode();
        if (NIL_P(val)) return INT2FIX(fo);
        sw = check_rounding_mode(val);
        fo = VpSetRoundMode(sw);
        return INT2FIX(fo);
    }
    rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
    return Qnil;
}

Возвращает целое число, представляющее параметры режима для обработки исключений и округления.

Эти режимы управляют обработкой исключений:

  • BigDecimal::EXCEPTION_NaN.

  • BigDecimal::EXCEPTION_INFINITY.

  • BigDecimal::EXCEPTION_UNDERFLOW.

  • BigDecimal::EXCEPTION_OVERFLOW.

  • BigDecimal::EXCEPTION_ZERODIVIDE.

  • BigDecimal::EXCEPTION_ALL.

Значения для setting для обработки исключений:

  • true: устанавливает указанный mode в true.

  • false: устанавливает указанный mode в false.

  • nil: не изменяет настройки режима.

Вы можете использовать метод BigDecimal.save_exception_mode для временного изменения и последующего автоматического восстановления режимов обработки исключений.

Для ясности, некоторые примеры ниже начинают с установки всех режимов обработки исключений в false.

Этот режим управляет способом выполнения округления:

  • BigDecimal::ROUND_MODE

Вы можете использовать метод BigDecimal.save_rounding_mode для временного изменения и последующего автоматического восстановления режима округления.

NaN

Режим BigDecimal::EXCEPTION_NaN управляет поведением при создании BigDecimal NaN.

Настройки:

  • false (по умолчанию): Возвращает BigDecimal('NaN').

  • true: Вызывает FloatDomainError.

Примеры:

BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
BigDecimal('NaN')                                 # => NaN
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true)  # => 2
BigDecimal('NaN') # Raises FloatDomainError

Бесконечности

Режим BigDecimal::EXCEPTION_INFINITY управляет поведением при создании BigDecimal Infinity или -Infinity. Настройки:

  • false (по умолчанию): Возвращает BigDecimal('Infinity') или BigDecimal('-Infinity').

  • true: Вызывает FloatDomainError.

Примеры:

BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false)     # => 0
BigDecimal('Infinity')                                # => Infinity
BigDecimal('-Infinity')                               # => -Infinity
BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1
BigDecimal('Infinity')  # Raises FloatDomainError
BigDecimal('-Infinity') # Raises FloatDomainError

Подпоток

Режим BigDecimal::EXCEPTION_UNDERFLOW управляет поведением при возникновении подпотока BigDecimal. Настройки:

  • false (по умолчанию): Возвращает BigDecimal('0') или BigDecimal('-Infinity').

  • true: Вызывает FloatDomainError.

Примеры:

BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false)      # => 0
def flow_under
  x = BigDecimal('0.1')
  100.times { x *= x }
end
flow_under                                             # => 100
BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4
flow_under # Raises FloatDomainError

Переполнение

Режим BigDecimal::EXCEPTION_OVERFLOW управляет поведением при возникновении переполнения BigDecimal. Настройки:

  • false (по умолчанию): Возвращает BigDecimal('Infinity') или BigDecimal('-Infinity').

  • true: Вызывает FloatDomainError.

Примеры:

BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false)     # => 0
def flow_over
  x = BigDecimal('10')
  100.times { x *= x }
end
flow_over                                             # => 100
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1
flow_over # Raises FloatDomainError

Деление на ноль

Режим BigDecimal::EXCEPTION_ZERODIVIDE управляет поведением при делении на ноль. Настройки:

  • false (по умолчанию): Возвращает BigDecimal('Infinity') или BigDecimal('-Infinity').

  • true: Вызывает FloatDomainError.

Примеры:

BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false)       # => 0
one = BigDecimal('1')
zero = BigDecimal('0')
one / zero                                              # => Infinity
BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16
one / zero # Raises FloatDomainError

Все исключения

Режим BigDecimal::EXCEPTION_ALL управляет всеми вышеперечисленными:

BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true)  # => 23

Округление

Режим BigDecimal::ROUND_MODE управляет способом выполнения округления; его значения:

  • ROUND_UP: Округляет в сторону от нуля. Также известен как :up.

  • ROUND_DOWN: Округляет к нулю. Также известен как :down и :truncate.

  • ROUND_HALF_UP: Округляет к ближайшему соседу; если соседи равноудалены, округляет в сторону от нуля. Также известен как :half_up и :default.

  • ROUND_HALF_DOWN: Округляет к ближайшему соседу; если соседи равноудалены, округляет к нулю. Также известен как :half_down.

  • ROUND_HALF_EVEN (округление по правилам банковского округления): Округляет к ближайшему соседу; если соседи равноудалены, округляет к четному соседу. Также известен как :half_even и :banker.

  • ROUND_CEILING: Округляет к положительной бесконечности. Также известен как :ceiling и :ceil.

  • ROUND_FLOOR: Округляет к отрицательной бесконечности. Также известен как :floor:.

save_exception_mode { ... } Показать исходный код
static VALUE
BigDecimal_save_exception_mode(VALUE self)
{
    unsigned short const exception_mode = VpGetException();
    int state;
    VALUE ret = rb_protect(rb_yield, Qnil, &state);
    VpSetException(exception_mode);
    if (state) rb_jump_tag(state);
    return ret;
}

Выполнить предоставленный блок, но сохранить режим исключений

BigDecimal.save_exception_mode do
  BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
  BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)

  BigDecimal(BigDecimal('Infinity'))
  BigDecimal(BigDecimal('-Infinity'))
  BigDecimal(BigDecimal('NaN'))
end

Для использования с BigDecimal::EXCEPTION_*

См. BigDecimal.mode

save_limit { ... } Показать исходный код
static VALUE
BigDecimal_save_limit(VALUE self)
{
    size_t const limit = VpGetPrecLimit();
    int state;
    VALUE ret = rb_protect(rb_yield, Qnil, &state);
    VpSetPrecLimit(limit);
    if (state) rb_jump_tag(state);
    return ret;
}

Выполнить предоставленный блок, но сохранить предел точности

BigDecimal.limit(100)
puts BigDecimal.limit
BigDecimal.save_limit do
    BigDecimal.limit(200)
    puts BigDecimal.limit
end
puts BigDecimal.limit
save_rounding_mode { ... } Показать исходный код
static VALUE
BigDecimal_save_rounding_mode(VALUE self)
{
    unsigned short const round_mode = VpGetRoundMode();
    int state;
    VALUE ret = rb_protect(rb_yield, Qnil, &state);
    VpSetRoundMode(round_mode);
    if (state) rb_jump_tag(state);
    return ret;
}

Выполнить предоставленный блок, но сохранить режим округления

BigDecimal.save_rounding_mode do
  BigDecimal.mode(BigDecimal::ROUND_MODE, :up)
  puts BigDecimal.mode(BigDecimal::ROUND_MODE)
end

Для использования с BigDecimal::ROUND_*

См. BigDecimal.mode

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

a % b Показать исходный код
static VALUE
BigDecimal_mod(VALUE self, VALUE r) 

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

См. BigDecimal#divmod.

Также алиасируется как: modulo
*(p1) Показать исходный код
static VALUE
BigDecimal_mult(VALUE self, VALUE r)
{
    ENTER(5);
    Real *c, *a, *b;
    size_t mx;

    GUARD_OBJ(a, GetVpValue(self, 1));
    if (RB_TYPE_P(r, T_FLOAT)) {
        b = GetVpValueWithPrec(r, 0, 1);
    }
    else if (RB_TYPE_P(r, T_RATIONAL)) {
        b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
    }
    else {
        b = GetVpValue(r,0);
    }

    if (!b) return DoSomeOne(self, r, '*');
    SAVE(b);

    mx = a->Prec + b->Prec;
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
    VpMult(c, a, b);
    return VpCheckGetValue(c);
}
self ** other → bigdecimal Показать исходный код
static VALUE
BigDecimal_power_op(VALUE self, VALUE exp)
{
    return BigDecimal_power(1, &exp, self);
}

Возвращает значение BigDecimal для self в степени other:

b = BigDecimal('3.14')
b ** 2              # => 0.98596e1
b ** 2.0            # => 0.98596e1
b ** Rational(2, 1) # => 0.98596e1

Связанно с: BigDecimal#power.

self + value → bigdecimal Показать исходный код
static VALUE
BigDecimal_add(VALUE self, VALUE r)
{
    ENTER(5);
    Real *c, *a, *b;
    size_t mx;

    GUARD_OBJ(a, GetVpValue(self, 1));
    if (RB_TYPE_P(r, T_FLOAT)) {
        b = GetVpValueWithPrec(r, 0, 1);
    }
    else if (RB_TYPE_P(r, T_RATIONAL)) {
        b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
    }
    else {
        b = GetVpValue(r, 0);
    }

    if (!b) return DoSomeOne(self,r,'+');
    SAVE(b);

    if (VpIsNaN(b)) return b->obj;
    if (VpIsNaN(a)) return a->obj;

    mx = GetAddSubPrec(a, b);
    if (mx == (size_t)-1L) {
        GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
        VpAddSub(c, a, b, 1);
    }
    else {
        GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
        if (!mx) {
            VpSetInf(c, VpGetSign(a));
        }
        else {
            VpAddSub(c, a, b, 1);
        }
    }
    return VpCheckGetValue(c);
}

Возвращает сумму BigDecimal для self и value:

b = BigDecimal('111111.111') # => 0.111111111e6
b + 2                        # => 0.111113111e6
b + 2.0                      # => 0.111113111e6
b + Rational(2, 1)           # => 0.111113111e6
b + Complex(2, 0)            # => (0.111113111e6+0i)

См. Примечание о точности.

+big_decimal → self Показать исходный код
static VALUE
BigDecimal_uplus(VALUE self)
{
    return self;
}

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

+BigDecimal(5)  # => 0.5e1
+BigDecimal(-5) # => -0.5e1
self - value → bigdecimal Показать исходный код
static VALUE
BigDecimal_sub(VALUE self, VALUE r)
{
    ENTER(5);
    Real *c, *a, *b;
    size_t mx;

    GUARD_OBJ(a, GetVpValue(self,1));
    if (RB_TYPE_P(r, T_FLOAT)) {
        b = GetVpValueWithPrec(r, 0, 1);
    }
    else if (RB_TYPE_P(r, T_RATIONAL)) {
        b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
    }
    else {
        b = GetVpValue(r,0);
    }

    if (!b) return DoSomeOne(self,r,'-');
    SAVE(b);

    if (VpIsNaN(b)) return b->obj;
    if (VpIsNaN(a)) return a->obj;

    mx = GetAddSubPrec(a,b);
    if (mx == (size_t)-1L) {
        GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
        VpAddSub(c, a, b, -1);
    }
    else {
        GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1)));
        if (!mx) {
            VpSetInf(c,VpGetSign(a));
        }
        else {
            VpAddSub(c, a, b, -1);
        }
    }
    return VpCheckGetValue(c);
}

Возвращает разницу BigDecimal для self и value:

b = BigDecimal('333333.333') # => 0.333333333e6
b - 2                        # => 0.333331333e6
b - 2.0                      # => 0.333331333e6
b - Rational(2, 1)           # => 0.333331333e6
b - Complex(2, 0)            # => (0.333331333e6+0i)

См. Примечание о точности.

-self → bigdecimal Показать исходный код
static VALUE
BigDecimal_neg(VALUE self)
{
    ENTER(5);
    Real *c, *a;
    GUARD_OBJ(a, GetVpValue(self, 1));
    GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1)));
    VpAsgn(c, a, -1);
    return VpCheckGetValue(c);
}

Возвращает отрицание BigDecimal для self:

b0 = BigDecimal('1.5')
b1 = -b0 # => -0.15e1
b2 = -b1 # => 0.15e1
a / b → bigdecimal Показать исходный код
static VALUE
BigDecimal_div(VALUE self, VALUE r)
/* For c = self/r: with round operation */
{
    ENTER(5);
    Real *c=NULL, *res=NULL, *div = NULL;
    r = BigDecimal_divide(self, r, &c, &res, &div);
    if (!NIL_P(r)) return r; /* coerced by other */
    SAVE(c); SAVE(res); SAVE(div);
    /* a/b = c + r/b */
    /* c xxxxx
       r 00000yyyyy  ==> (y/b)*BASE >= HALF_BASE
     */
    /* Round */
    if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
        VpInternalRound(c, 0, c->frac[c->Prec-1], (DECDIG)(VpBaseVal() * (DECDIG_DBL)res->frac[0] / div->frac[0]));
    }
    return VpCheckGetValue(c);
}

Деление на указанное значение.

Точность результата будет равна точности большего операнда, но не меньше 2*Float::DIG.

См. BigDecimal#div. См. BigDecimal#quo.

self < other → true или false Показать исходный код
static VALUE
BigDecimal_lt(VALUE self, VALUE r)
{
    return BigDecimalCmp(self, r, '<');
}

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

b = BigDecimal('1.5') # => 0.15e1
b < 2                 # => true
b < 2.0               # => true
b < Rational(2, 1)    # => true
b < 1.5               # => false

Вызывает исключение, если сравнение невозможно.

self <= other → true или false Показать исходный код
static VALUE
BigDecimal_le(VALUE self, VALUE r)
{
    return BigDecimalCmp(self, r, 'L');
}

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

b = BigDecimal('1.5') # => 0.15e1
b <= 2                # => true
b <= 2.0              # => true
b <= Rational(2, 1)   # => true
b <= 1.5              # => true
b < 1                 # => false

Вызывает исключение, если сравнение невозможно.

<=>(p1) Показать исходный код
static VALUE
BigDecimal_comp(VALUE self, VALUE r)
{
    return BigDecimalCmp(self, r, '*');
}

Оператор сравнения. a <=> b равен 0, если a == b, 1, если a > b, -1, если a < b.

==(p1) Показать исходный код
static VALUE
BigDecimal_eq(VALUE self, VALUE r)
{
    return BigDecimalCmp(self, r, '=');
}

Проверка равенства значений; возвращает true, если значения равны.

Операторы == и ===, а также метод eql? имеют одинаковую реализацию для BigDecimal.

Значения могут быть приведены для выполнения сравнения:

BigDecimal('1.0') == 1.0  #=> true
Также алиасируется как: ===, eql?
===(p1)

Проверка равенства значений; возвращает true, если значения равны.

Операторы == и ===, а также метод eql? имеют одинаковую реализацию для BigDecimal.

Значения могут быть приведены для выполнения сравнения:

BigDecimal('1.0') == 1.0  #=> true
Псевдоним для: ==
self > other → true или false Показать исходный код
static VALUE
BigDecimal_gt(VALUE self, VALUE r)
{
    return BigDecimalCmp(self, r, '>');
}

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

b = BigDecimal('1.5')
b > 1              # => true
b > 1.0            # => true
b > Rational(1, 1) # => true
b > 2              # => false

Вызывает исключение, если сравнение невозможно.

self >= other → true или false Показать исходный код
static VALUE
BigDecimal_ge(VALUE self, VALUE r)
{
    return BigDecimalCmp(self, r, 'G');
}

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

b = BigDecimal('1.5')
b >= 1              # => true
b >= 1.0            # => true
b >= Rational(1, 1) # => true
b >= 1.5            # => true
b > 2               # => false

Вызывает исключение, если сравнение невозможно.

_dump → строка Показать исходный код
static VALUE
BigDecimal_dump(int argc, VALUE *argv, VALUE self)
{
    ENTER(5);
    Real *vp;
    char *psz;
    VALUE dummy;
    volatile VALUE dump;
    size_t len;

    rb_scan_args(argc, argv, "01", &dummy);
    GUARD_OBJ(vp,GetVpValue(self, 1));
    dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
    psz = RSTRING_PTR(dump);
    snprintf(psz, RSTRING_LEN(dump), "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
    len = strlen(psz);
    VpToString(vp, psz+len, RSTRING_LEN(dump)-len, 0, 0);
    rb_str_resize(dump, strlen(psz));
    return dump;
}

Возвращает строку, представляющую маршаллинг self. См. модуль Marshal.

inf = BigDecimal('Infinity') # => Infinity
dumped = inf._dump           # => "9:Infinity"
BigDecimal._load(dumped)     # => Infinity
abs → bigdecimal Показать исходный код
static VALUE
BigDecimal_abs(VALUE self)
{
    ENTER(5);
    Real *c, *a;
    size_t mx;

    GUARD_OBJ(a, GetVpValue(self, 1));
    mx = a->Prec *(VpBaseFig() + 1);
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
    VpAsgn(c, a, 1);
    VpChangeSign(c, 1);
    return VpCheckGetValue(c);
}

Возвращает абсолютное значение BigDecimal для self:

BigDecimal('5').abs  # => 0.5e1
BigDecimal('-3').abs # => 0.3e1
add(value, ndigits) → new_bigdecimal Показать исходный код
static VALUE
BigDecimal_add2(VALUE self, VALUE b, VALUE n)
{
    ENTER(2);
    Real *cv;
    SIGNED_VALUE mx = check_int_precision(n);
    if (mx == 0) return BigDecimal_add(self, b);
    else {
        size_t pl = VpSetPrecLimit(0);
        VALUE   c = BigDecimal_add(self, b);
        VpSetPrecLimit(pl);
        GUARD_OBJ(cv, GetVpValue(c, 1));
        VpLeftRound(cv, VpGetRoundMode(), mx);
        return VpCheckGetValue(cv);
    }
}

Возвращает сумму BigDecimal для self и value с точностью ndigits десятичных знаков.

Когда ndigits меньше количества значащих цифр в сумме, сумма округляется до этого количества цифр в соответствии с текущим режимом округления; см. BigDecimal.mode.

Примеры:

# Set the rounding mode.
BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
b = BigDecimal('111111.111')
b.add(1, 0)               # => 0.111112111e6
b.add(1, 3)               # => 0.111e6
b.add(1, 6)               # => 0.111112e6
b.add(1, 15)              # => 0.111112111e6
b.add(1.0, 15)            # => 0.111112111e6
b.add(Rational(1, 1), 15) # => 0.111112111e6
as_json(*) Показать исходный код
# File ext/json/lib/json/add/bigdecimal.rb, line 35
def as_json(*)
  {
    JSON.create_id => self.class.name,
    'b'            => _dump,
  }
end

Методы BigDecimal#as_json и BigDecimal.json_create могут быть использованы для сериализации и десериализации объекта BigDecimal; см. Marshal.

Метод BigDecimal#as_json сериализует self, возвращая хеш из 2 элементов, представляющий self:

require 'json/add/bigdecimal'
x = BigDecimal(2).as_json             # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
y = BigDecimal(2.0, 4).as_json        # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"}
z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}

Метод JSON.create десериализует такой хеш, возвращая объект BigDecimal:

BigDecimal.json_create(x) # => 0.2e1
BigDecimal.json_create(y) # => 0.2e1
BigDecimal.json_create(z) # => 0.2e1
END_OF_DOCUMENT_MARKER
ceil(n) Показать исходный код
static VALUE
BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
{
    ENTER(5);
    Real *c, *a;
    int iLoc;
    VALUE vLoc;
    size_t mx, pl = VpSetPrecLimit(0);

    if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
        iLoc = 0;
    } else {
        iLoc = NUM2INT(vLoc);
    }

    GUARD_OBJ(a, GetVpValue(self, 1));
    mx = a->Prec * (VpBaseFig() + 1);
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
    VpSetPrecLimit(pl);
    VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
    if (argc == 0) {
        return BigDecimal_to_i(VpCheckGetValue(c));
    }
    return VpCheckGetValue(c);
}

Возвращает наименьшее целое число, большее или равное значению, в виде BigDecimal.

BigDecimal('3.14159').ceil #=> 4
BigDecimal('-9.1').ceil #=> -9

Если n задано и положительно, дробная часть результата содержит не более указанного количества цифр.

Если n задано и отрицательно, в результате слева от десятичной точки будет по крайней мере столько цифр, равных 0.

BigDecimal('3.14159').ceil(3) #=> 3.142
BigDecimal('13345.234').ceil(-2) #=> 13400.0
clone() Показать исходный код
static VALUE
BigDecimal_clone(VALUE self)
{
  return self;
}
Также алиасируется как: dup
coerce(p1) Показать исходный код
static VALUE
BigDecimal_coerce(VALUE self, VALUE other)
{
    ENTER(2);
    VALUE obj;
    Real *b;

    if (RB_TYPE_P(other, T_FLOAT)) {
        GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1));
        obj = rb_assoc_new(VpCheckGetValue(b), self);
    }
    else {
        if (RB_TYPE_P(other, T_RATIONAL)) {
            Real* pv = DATA_PTR(self);
            GUARD_OBJ(b, GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1));
        }
        else {
            GUARD_OBJ(b, GetVpValue(other, 1));
        }
        obj = rb_assoc_new(b->obj, self);
    }

    return obj;
}

Метод coerce обеспечивает поддержку приведения типов в Ruby. По умолчанию он не включен.

Это означает, что бинарные операции, такие как +, *, / или -, часто могут выполняться над BigDecimal и объектом другого типа, если другой объект может быть приведен к значению BigDecimal.

Например:

a = BigDecimal("1.0")
b = a / 2.0 #=> 0.5

Обратите внимание, что приведение String к BigDecimal по умолчанию не поддерживается; для этого требуется специальный параметр компиляции при сборке Ruby.

div(value) → integer Показать исходный код
div(value, digits) → bigdecimal or integer
static VALUE
BigDecimal_div3(int argc, VALUE *argv, VALUE self)
{
    VALUE b,n;

    rb_scan_args(argc, argv, "11", &b, &n);

    return BigDecimal_div2(self, b, n);
}

Деление на указанное значение.

digits

Если задано и меньше, чем количество значащих цифр результата, результат округляется до этого количества цифр в соответствии с BigDecimal.mode.

Если digits равно 0, результат такой же, как для оператора / или quo.

Если digits не задано, результат — целое число, аналогично Float#div; см. также BigDecimal#divmod.

См. BigDecimal#/. См. BigDecimal#quo.

Примеры:

a = BigDecimal("4")
b = BigDecimal("3")

a.div(b, 3)  # => 0.133e1

a.div(b, 0)  # => 0.1333333333333333333e1
a / b        # => 0.1333333333333333333e1
a.quo(b)     # => 0.1333333333333333333e1

a.div(b)     # => 1
divmod(value) Показать исходный код
static VALUE
BigDecimal_divmod(VALUE self, VALUE r)
{
    ENTER(5);
    Real *div = NULL, *mod = NULL;

    if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
        SAVE(div); SAVE(mod);
        return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod));
    }
    return DoSomeOne(self,r,rb_intern("divmod"));
}

Делит на заданное значение и возвращает частное и остаток как числа BigDecimal. Частное округляется к отрицательной бесконечности.

Например:

require 'bigdecimal'

a = BigDecimal("42")
b = BigDecimal("9")

q, m = a.divmod(b)

c = q * b + m

a == c  #=> true

Частное q равно (a/b).floor, а остаток — величина, которую необходимо добавить к q * b, чтобы получить a.

dup()
Псевдоним для: clone
eql?(p1)

Проверяет равенство значений; возвращает true, если значения равны.

Операторы == и ===, а также метод eql? имеют одинаковую реализацию для BigDecimal.

Значения могут быть приведены для выполнения сравнения:

BigDecimal('1.0') == 1.0  #=> true
Псевдоним для: ==
exponent() Показать исходный код
static VALUE
BigDecimal_exponent(VALUE self)
{
    ssize_t e = VpExponent10(GetVpValue(self, 1));
    return SSIZET2NUM(e);
}

Возвращает показатель степени числа BigDecimal как целое число Integer.

Если число можно представить как 0.xxxxxx*10**n, где xxxxxx — строка цифр без ведущих нулей, то n — показатель степени.

finite?() Показать исходный код
static VALUE
BigDecimal_IsFinite(VALUE self)
{
    Real *p = GetVpValue(self, 1);
    if (VpIsNaN(p)) return Qfalse;
    if (VpIsInf(p)) return Qfalse;
    return Qtrue;
}

Возвращает True, если значение конечно (не NaN и не бесконечно).

fix() Показать исходный код
static VALUE
BigDecimal_fix(VALUE self)
{
    ENTER(5);
    Real *c, *a;
    size_t mx;

    GUARD_OBJ(a, GetVpValue(self, 1));
    mx = a->Prec *(VpBaseFig() + 1);
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
    VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
    return VpCheckGetValue(c);
}

Возвращает целую часть числа в виде BigDecimal.

floor(n) Показать исходный код
static VALUE
BigDecimal_floor(int argc, VALUE *argv, VALUE self)
{
    ENTER(5);
    Real *c, *a;
    int iLoc;
    VALUE vLoc;
    size_t mx, pl = VpSetPrecLimit(0);

    if (rb_scan_args(argc, argv, "01", &vLoc)==0) {
        iLoc = 0;
    }
    else {
        iLoc = NUM2INT(vLoc);
    }

    GUARD_OBJ(a, GetVpValue(self, 1));
    mx = a->Prec * (VpBaseFig() + 1);
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
    VpSetPrecLimit(pl);
    VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
#ifdef BIGDECIMAL_DEBUG
    VPrint(stderr, "floor: c=%\n", c);
#endif
    if (argc == 0) {
        return BigDecimal_to_i(VpCheckGetValue(c));
    }
    return VpCheckGetValue(c);
}

Возвращает наибольшее целое число, меньшее или равное значению, в виде BigDecimal.

BigDecimal('3.14159').floor #=> 3
BigDecimal('-9.1').floor #=> -10

Если n задано и положительно, дробная часть результата содержит не более указанного количества цифр.

Если n задано и отрицательно, в результате слева от десятичной точки будет по крайней мере столько цифр, равных 0.

BigDecimal('3.14159').floor(3) #=> 3.141
BigDecimal('13345.234').floor(-2) #=> 13300.0
frac() Показать исходный код
static VALUE
BigDecimal_frac(VALUE self)
{
    ENTER(5);
    Real *c, *a;
    size_t mx;

    GUARD_OBJ(a, GetVpValue(self, 1));
    mx = a->Prec * (VpBaseFig() + 1);
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
    VpFrac(c, a);
    return VpCheckGetValue(c);
}

Возвращает дробную часть числа в виде BigDecimal.

hash → integer Показать исходный код
static VALUE
BigDecimal_hash(VALUE self)
{
    ENTER(1);
    Real *p;
    st_index_t hash;

    GUARD_OBJ(p, GetVpValue(self, 1));
    hash = (st_index_t)p->sign;
    /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
    if(hash == 2 || hash == (st_index_t)-2) {
        hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec);
        hash += p->exponent;
    }
    return ST2FIX(hash);
}

Возвращает целочисленное значение хэша для self.

Два экземпляра BigDecimal имеют одинаковое значение хэша тогда и только тогда, когда у них равны:

  • Знак.

  • Дробная часть.

  • Показатель степени.

infinite?() Показать исходный код
static VALUE
BigDecimal_IsInfinite(VALUE self)
{
    Real *p = GetVpValue(self, 1);
    if (VpIsPosInf(p)) return INT2FIX(1);
    if (VpIsNegInf(p)) return INT2FIX(-1);
    return Qnil;
}

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

inspect() Показать исходный код
static VALUE
BigDecimal_inspect(VALUE self)
{
    ENTER(5);
    Real *vp;
    volatile VALUE str;
    size_t nc;

    GUARD_OBJ(vp, GetVpValue(self, 1));
    nc = VpNumOfChars(vp, "E");

    str = rb_str_new(0, nc);
    VpToString(vp, RSTRING_PTR(str), RSTRING_LEN(str), 0, 0);
    rb_str_resize(str, strlen(RSTRING_PTR(str)));
    return str;
}

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

BigDecimal("1234.5678").inspect
  #=> "0.12345678e4"
modulo(b)

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

См. BigDecimal#divmod.

Псевдоним для: %
mult(other, ndigits) → bigdecimal Показать исходный код
static VALUE
BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
{
    ENTER(2);
    Real *cv;
    SIGNED_VALUE mx = check_int_precision(n);
    if (mx == 0) return BigDecimal_mult(self, b);
    else {
        size_t pl = VpSetPrecLimit(0);
        VALUE   c = BigDecimal_mult(self, b);
        VpSetPrecLimit(pl);
        GUARD_OBJ(cv, GetVpValue(c, 1));
        VpLeftRound(cv, VpGetRoundMode(), mx);
        return VpCheckGetValue(cv);
    }
}

Возвращает произведение BigDecimal self и value с точностью до ndigits десятичных цифр.

Когда ndigits меньше количества значащих цифр в сумме, сумма округляется до этого количества цифр в соответствии с текущим режимом округления; см. BigDecimal.mode.

Примеры:

# Set the rounding mode.
BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
b = BigDecimal('555555.555')
b.mult(3, 0)              # => 0.1666666665e7
b.mult(3, 3)              # => 0.167e7
b.mult(3, 6)              # => 0.166667e7
b.mult(3, 15)             # => 0.1666666665e7
b.mult(3.0, 0)            # => 0.1666666665e7
b.mult(Rational(3, 1), 0) # => 0.1666666665e7
b.mult(Complex(3, 0), 0)  # => (0.1666666665e7+0.0i)
n_significant_digits → integer Показать исходный код
static VALUE
BigDecimal_n_significant_digits(VALUE self)
{
    ENTER(1);

    Real *p;
    GUARD_OBJ(p, GetVpValue(self, 1));
    if (VpIsZero(p) || !VpIsDef(p)) {
        return INT2FIX(0);
    }

    ssize_t n = p->Prec;  /* The length of frac without trailing zeros. */
    for (n = p->Prec; n > 0 && p->frac[n-1] == 0; --n);
    if (n == 0) return INT2FIX(0);

    DECDIG x;
    int nlz = BASE_FIG;
    for (x = p->frac[0]; x > 0; x /= 10) --nlz;

    int ntz = 0;
    for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;

    ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz;
    return SSIZET2NUM(n_significant_digits);
}

Возвращает количество значащих десятичных цифр в self.

BigDecimal("0").n_significant_digits         # => 0
BigDecimal("1").n_significant_digits         # => 1
BigDecimal("1.1").n_significant_digits       # => 2
BigDecimal("3.1415").n_significant_digits    # => 5
BigDecimal("-1e20").n_significant_digits     # => 1
BigDecimal("1e-20").n_significant_digits     # => 1
BigDecimal("Infinity").n_significant_digits  # => 0
BigDecimal("-Infinity").n_significant_digits # => 0
BigDecimal("NaN").n_significant_digits       # => 0
nan?() Показать исходный код
static VALUE
BigDecimal_IsNaN(VALUE self)
{
    Real *p = GetVpValue(self, 1);
    if (VpIsNaN(p))  return Qtrue;
    return Qfalse;
}

Возвращает True, если значение равно Not a Number.

END_OF_DOCUMENT_MARKER
nonzero?() Показать исходный код
static VALUE
BigDecimal_nonzero(VALUE self)
{
    Real *a = GetVpValue(self, 1);
    return VpIsZero(a) ? Qnil : self;
}

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

power(n) Показать исходный код
power(n, prec)
static VALUE
BigDecimal_power(int argc, VALUE*argv, VALUE self)
{
    ENTER(5);
    VALUE vexp, prec;
    Real* exp = NULL;
    Real *x, *y;
    ssize_t mp, ma, n;
    SIGNED_VALUE int_exp;
    double d;

    rb_scan_args(argc, argv, "11", &vexp, &prec);

    GUARD_OBJ(x, GetVpValue(self, 1));
    n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);

    if (VpIsNaN(x)) {
        y = NewZeroWrapLimited(1, n);
        VpSetNaN(y);
        RB_GC_GUARD(y->obj);
        return VpCheckGetValue(y);
    }

  retry:
    switch (TYPE(vexp)) {
      case T_FIXNUM:
        break;

      case T_BIGNUM:
        break;

      case T_FLOAT:
        d = RFLOAT_VALUE(vexp);
        if (d == round(d)) {
            if (FIXABLE(d)) {
                vexp = LONG2FIX((long)d);
            }
            else {
                vexp = rb_dbl2big(d);
            }
            goto retry;
        }
        if (NIL_P(prec)) {
            n += BIGDECIMAL_DOUBLE_FIGURES;
        }
        exp = GetVpValueWithPrec(vexp, 0, 1);
        break;

      case T_RATIONAL:
        if (is_zero(rb_rational_num(vexp))) {
            if (is_positive(vexp)) {
                vexp = INT2FIX(0);
                goto retry;
            }
        }
        else if (is_one(rb_rational_den(vexp))) {
            vexp = rb_rational_num(vexp);
            goto retry;
        }
        exp = GetVpValueWithPrec(vexp, n, 1);
        if (NIL_P(prec)) {
            n += n;
        }
        break;

      case T_DATA:
        if (is_kind_of_BigDecimal(vexp)) {
            VALUE zero = INT2FIX(0);
            VALUE rounded = BigDecimal_round(1, &zero, vexp);
            if (RTEST(BigDecimal_eq(vexp, rounded))) {
                vexp = BigDecimal_to_i(vexp);
                goto retry;
            }
            if (NIL_P(prec)) {
                GUARD_OBJ(y, GetVpValue(vexp, 1));
                n += y->Prec*VpBaseFig();
            }
            exp = DATA_PTR(vexp);
            break;
        }
        /* fall through */
      default:
        rb_raise(rb_eTypeError,
                 "wrong argument type %"PRIsVALUE" (expected scalar Numeric)",
                 RB_OBJ_CLASSNAME(vexp));
    }

    if (VpIsZero(x)) {
        if (is_negative(vexp)) {
            y = NewZeroWrapNolimit(1, n);
            if (BIGDECIMAL_NEGATIVE_P(x)) {
                if (is_integer(vexp)) {
                    if (is_even(vexp)) {
                        /* (-0) ** (-even_integer)  -> Infinity */
                        VpSetPosInf(y);
                    }
                    else {
                        /* (-0) ** (-odd_integer)  -> -Infinity */
                        VpSetNegInf(y);
                    }
                }
                else {
                    /* (-0) ** (-non_integer)  -> Infinity */
                    VpSetPosInf(y);
                }
            }
            else {
                /* (+0) ** (-num)  -> Infinity */
                VpSetPosInf(y);
            }
            RB_GC_GUARD(y->obj);
            return VpCheckGetValue(y);
        }
        else if (is_zero(vexp)) {
            return VpCheckGetValue(NewOneWrapLimited(1, n));
        }
        else {
            return VpCheckGetValue(NewZeroWrapLimited(1, n));
        }
    }

    if (is_zero(vexp)) {
        return VpCheckGetValue(NewOneWrapLimited(1, n));
    }
    else if (is_one(vexp)) {
        return self;
    }

    if (VpIsInf(x)) {
        if (is_negative(vexp)) {
            if (BIGDECIMAL_NEGATIVE_P(x)) {
                if (is_integer(vexp)) {
                    if (is_even(vexp)) {
                        /* (-Infinity) ** (-even_integer) -> +0 */
                        return VpCheckGetValue(NewZeroWrapLimited(1, n));
                    }
                    else {
                        /* (-Infinity) ** (-odd_integer) -> -0 */
                        return VpCheckGetValue(NewZeroWrapLimited(-1, n));
                    }
                }
                else {
                    /* (-Infinity) ** (-non_integer) -> -0 */
                    return VpCheckGetValue(NewZeroWrapLimited(-1, n));
                }
            }
            else {
                return VpCheckGetValue(NewZeroWrapLimited(1, n));
            }
        }
        else {
            y = NewZeroWrapLimited(1, n);
            if (BIGDECIMAL_NEGATIVE_P(x)) {
                if (is_integer(vexp)) {
                    if (is_even(vexp)) {
                        VpSetPosInf(y);
                    }
                    else {
                        VpSetNegInf(y);
                    }
                }
                else {
                    /* TODO: support complex */
                    rb_raise(rb_eMathDomainError,
                            "a non-integral exponent for a negative base");
                }
            }
            else {
                VpSetPosInf(y);
            }
            return VpCheckGetValue(y);
        }
    }

    if (exp != NULL) {
        return bigdecimal_power_by_bigdecimal(x, exp, n);
    }
    else if (RB_TYPE_P(vexp, T_BIGNUM)) {
        VALUE abs_value = BigDecimal_abs(self);
        if (is_one(abs_value)) {
            return VpCheckGetValue(NewOneWrapLimited(1, n));
        }
        else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
            if (is_negative(vexp)) {
                y = NewZeroWrapLimited(1, n);
                VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
                return VpCheckGetValue(y);
            }
            else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
                return VpCheckGetValue(NewZeroWrapLimited(-1, n));
            }
            else {
                return VpCheckGetValue(NewZeroWrapLimited(1, n));
            }
        }
        else {
            if (is_positive(vexp)) {
                y = NewZeroWrapLimited(1, n);
                VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
                return VpCheckGetValue(y);
            }
            else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
                return VpCheckGetValue(NewZeroWrapLimited(-1, n));
            }
            else {
                return VpCheckGetValue(NewZeroWrapLimited(1, n));
            }
        }
    }

    int_exp = FIX2LONG(vexp);
    ma = int_exp;
    if (ma <  0) ma = -ma;
    if (ma == 0) ma = 1;

    if (VpIsDef(x)) {
        mp = x->Prec * (VpBaseFig() + 1);
        GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1)));
    }
    else {
        GUARD_OBJ(y, NewZeroWrapLimited(1, 1));
    }
    VpPowerByInt(y, x, int_exp);
    if (!NIL_P(prec) && VpIsDef(y)) {
        VpMidRound(y, VpGetRoundMode(), n);
    }
    return VpCheckGetValue(y);
}

Возвращает значение, возведённое в степень n.

Обратите внимание, что n должно быть Integer.

Также доступно как оператор **.

precision → integer Показать исходный код
static VALUE
BigDecimal_precision(VALUE self)
{
    ssize_t precision;
    BigDecimal_count_precision_and_scale(self, &precision, NULL);
    return SSIZET2NUM(precision);
}

Возвращает количество десятичных знаков в self:

BigDecimal("0").precision         # => 0
BigDecimal("1").precision         # => 1
BigDecimal("1.1").precision       # => 2
BigDecimal("3.1415").precision    # => 5
BigDecimal("-1e20").precision     # => 21
BigDecimal("1e-20").precision     # => 20
BigDecimal("Infinity").precision  # => 0
BigDecimal("-Infinity").precision # => 0
BigDecimal("NaN").precision       # => 0
precision_scale → [integer, integer] Показать исходный код
static VALUE
BigDecimal_precision_scale(VALUE self)
{
    ssize_t precision, scale;
    BigDecimal_count_precision_and_scale(self, &precision, &scale);
    return rb_assoc_new(SSIZET2NUM(precision), SSIZET2NUM(scale));
}

Возвращает массив длины 2; первый элемент — результат вызова BigDecimal#precision, а второй — результат BigDecimal#scale.

См. BigDecimal#precision. См. BigDecimal#scale.

precs → array Показать исходный код
static VALUE
BigDecimal_prec(VALUE self)
{
    ENTER(1);
    Real *p;
    VALUE obj;

    rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
                     "BigDecimal#precs is deprecated and will be removed in the future; "
                     "use BigDecimal#precision instead.");

    GUARD_OBJ(p, GetVpValue(self, 1));
    obj = rb_assoc_new(SIZET2NUM(p->Prec*VpBaseFig()),
                       SIZET2NUM(p->MaxPrec*VpBaseFig()));
    return obj;
}

Возвращает Array из двух Integer значений, которые представляют платформенно-зависимые свойства внутреннего хранения.

Этот метод устарел и будет удалён в будущем. Вместо него используйте BigDecimal#n_significant_digits для получения количества значащих цифр в экспоненциальной форме и BigDecimal#precision для получения количества цифр в десятичной форме.

quo(value) → bigdecimal Показать исходный код
quo(value, digits) → bigdecimal
static VALUE
BigDecimal_quo(int argc, VALUE *argv, VALUE self)
{
    VALUE value, digits, result;
    SIGNED_VALUE n = -1;

    argc = rb_scan_args(argc, argv, "11", &value, &digits);
    if (argc > 1) {
        n = check_int_precision(digits);
    }

    if (n > 0) {
        result = BigDecimal_div2(self, value, digits);
    }
    else {
        result = BigDecimal_div(self, value);
    }

    return result;
}

Деление на указанное значение.

digits

Если указано и меньше числа значащих цифр результата, результат округляется до заданного количества цифр в соответствии с режимом округления, указанным в BigDecimal.mode.

Если digits равно 0 или опущено, результат такой же, как и для оператора /.

См. BigDecimal#/. См. BigDecimal#div.

remainder(value) Показать исходный код
static VALUE
BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
{
    VALUE  f;
    Real  *d, *rv = 0;
    f = BigDecimal_divremain(self, r, &d, &rv);
    if (!NIL_P(f)) return f;
    return VpCheckGetValue(rv);
}

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

x.remainder(y) означает x-y*(x/y).truncate

round(n, mode) Показать исходный код
static VALUE
BigDecimal_round(int argc, VALUE *argv, VALUE self)
{
    ENTER(5);
    Real   *c, *a;
    int    iLoc = 0;
    VALUE  vLoc;
    VALUE  vRound;
    int    round_to_int = 0;
    size_t mx, pl;

    unsigned short sw = VpGetRoundMode();

    switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) {
      case 0:
        iLoc = 0;
        round_to_int = 1;
        break;
      case 1:
        if (RB_TYPE_P(vLoc, T_HASH)) {
            sw = check_rounding_mode_option(vLoc);
        }
        else {
            iLoc = NUM2INT(vLoc);
            if (iLoc < 1) round_to_int = 1;
        }
        break;
      case 2:
        iLoc = NUM2INT(vLoc);
        if (RB_TYPE_P(vRound, T_HASH)) {
            sw = check_rounding_mode_option(vRound);
        }
        else {
            sw = check_rounding_mode(vRound);
        }
        break;
      default:
        break;
    }

    pl = VpSetPrecLimit(0);
    GUARD_OBJ(a, GetVpValue(self, 1));
    mx = a->Prec * (VpBaseFig() + 1);
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
    VpSetPrecLimit(pl);
    VpActiveRound(c, a, sw, iLoc);
    if (round_to_int) {
        return BigDecimal_to_i(VpCheckGetValue(c));
    }
    return VpCheckGetValue(c);
}

Округление до ближайшего целого (по умолчанию), возвращающее результат как BigDecimal, если n указано, или как Integer, если нет.

BigDecimal('3.14159').round #=> 3
BigDecimal('8.7').round #=> 9
BigDecimal('-9.9').round #=> -10

BigDecimal('3.14159').round(2).class.name #=> "BigDecimal"
BigDecimal('3.14159').round.class.name #=> "Integer"

Если n указано и положительно, дробная часть результата имеет не более указанного количества цифр.

Если n указано и отрицательно, в результате будет как минимум столько нулей слева от десятичной точки, и возвращаемое значение будет Integer.

BigDecimal('3.14159').round(3) #=> 3.142
BigDecimal('13345.234').round(-2) #=> 13300

Значение необязательного аргумента mode может использоваться для определения способа округления; см. BigDecimal.mode.

scale → integer Показать исходный код
static VALUE
BigDecimal_scale(VALUE self)
{
    ssize_t scale;
    BigDecimal_count_precision_and_scale(self, NULL, &scale);
    return SSIZET2NUM(scale);
}

Возвращает количество десятичных знаков после десятичной точки в self.

BigDecimal("0").scale         # => 0
BigDecimal("1").scale         # => 0
BigDecimal("1.1").scale       # => 1
BigDecimal("3.1415").scale    # => 4
BigDecimal("-1e20").precision # => 0
BigDecimal("1e-20").precision # => 20
BigDecimal("Infinity").scale  # => 0
BigDecimal("-Infinity").scale # => 0
BigDecimal("NaN").scale       # => 0
sign() Показать исходный код
static VALUE
BigDecimal_sign(VALUE self)
{ /* sign */
    int s = GetVpValue(self, 1)->sign;
    return INT2FIX(s);
}

Возвращает знак значения.

Возвращает положительное значение, если > 0, отрицательное, если < 0. Ведёт себя одинаково с нулями: возвращает положительное значение для положительного нуля (BigDecimal(‘0’)) и отрицательное значение для отрицательного нуля (BigDecimal(‘-0’)).

Конкретное возвращаемое значение указывает тип и знак BigDecimal, как показано ниже:

BigDecimal::SIGN_NaN

значение — Не число

BigDecimal::SIGN_POSITIVE_ZERO

значение — +0

BigDecimal::SIGN_NEGATIVE_ZERO

значение — -0

BigDecimal::SIGN_POSITIVE_INFINITE

значение — +Бесконечность

BigDecimal::SIGN_NEGATIVE_INFINITE

значение — -Бесконечность

BigDecimal::SIGN_POSITIVE_FINITE

значение — положительное

BigDecimal::SIGN_NEGATIVE_FINITE

значение — отрицательное

split() Показать исходный код
static VALUE
BigDecimal_split(VALUE self)
{
    ENTER(5);
    Real *vp;
    VALUE obj,str;
    ssize_t e, s;
    char *psz1;

    GUARD_OBJ(vp, GetVpValue(self, 1));
    str = rb_str_new(0, VpNumOfChars(vp, "E"));
    psz1 = RSTRING_PTR(str);
    VpSzMantissa(vp, psz1, RSTRING_LEN(str));
    s = 1;
    if(psz1[0] == '-') {
        size_t len = strlen(psz1 + 1);

        memmove(psz1, psz1 + 1, len);
        psz1[len] = '\0';
        s = -1;
    }
    if (psz1[0] == 'N') s = 0; /* NaN */
    e = VpExponent10(vp);
    obj = rb_ary_new2(4);
    rb_ary_push(obj, INT2FIX(s));
    rb_ary_push(obj, str);
    rb_str_resize(str, strlen(psz1));
    rb_ary_push(obj, INT2FIX(10));
    rb_ary_push(obj, SSIZET2NUM(e));
    return obj;
}

Разделяет число BigDecimal на четыре части, возвращая их в виде массива значений.

Первое значение представляет знак BigDecimal и равно -1 или 1, или 0, если BigDecimal — Не число.

Второе значение — строка, представляющая значащие цифры BigDecimal без ведущих нулей.

Третье значение — основание, используемое для арифметических операций (в настоящее время всегда 10), как Integer.

Четвёртое значение — показатель степени Integer.

Если BigDecimal может быть представлено как 0.xxxxxx*10**n, то xxxxxx — строка значащих цифр без ведущих нулей, а n — показатель степени.

По этим значениям можно перевести BigDecimal в float следующим образом:

sign, significant_digits, base, exponent = a.split
f = sign * "0.#{significant_digits}".to_f * (base ** exponent)

(Обратите внимание, что метод to_f предоставляется как более удобный способ преобразования BigDecimal в Float.)

sqrt(n) Показать исходный код
static VALUE
BigDecimal_sqrt(VALUE self, VALUE nFig)
{
    ENTER(5);
    Real *c, *a;
    size_t mx, n;

    GUARD_OBJ(a, GetVpValue(self, 1));
    mx = a->Prec * (VpBaseFig() + 1);

    n = check_int_precision(nFig);
    n += VpDblFig() + VpBaseFig();
    if (mx <= n) mx = n;
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
    VpSqrt(c, a);
    return VpCheckGetValue(c);
}

Возвращает квадратный корень из значения.

Результат имеет как минимум n значащих цифр.

sub(value, digits) → bigdecimal Показать исходный код
static VALUE
BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
{
    ENTER(2);
    Real *cv;
    SIGNED_VALUE mx = check_int_precision(n);
    if (mx == 0) return BigDecimal_sub(self, b);
    else {
        size_t pl = VpSetPrecLimit(0);
        VALUE   c = BigDecimal_sub(self, b);
        VpSetPrecLimit(pl);
        GUARD_OBJ(cv, GetVpValue(c, 1));
        VpLeftRound(cv, VpGetRoundMode(), mx);
        return VpCheckGetValue(cv);
    }
}

Вычитание указанного значения.

Например:

c = a.sub(b,n)
digits

Если указано и меньше числа значащих цифр результата, результат округляется до указанного количества цифр в соответствии с BigDecimal.mode.

to_d → bigdecimal Показать исходный код
# File ext/bigdecimal/lib/bigdecimal/util.rb, line 110
def to_d
  self
end

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

require 'bigdecimal/util'

d = BigDecimal("3.14")
d.to_d                       # => 0.314e1
to_digits → string Показать исходный код
# File ext/bigdecimal/lib/bigdecimal/util.rb, line 90
def to_digits
  if self.nan? || self.infinite? || self.zero?
    self.to_s
  else
    i       = self.to_i.to_s
    _,f,_,z = self.frac.split
    i + "." + ("0"*(-z)) + f
  end
end

Преобразование BigDecimal в строку формата «nnnnnn.mmm». Этот метод устарел; используйте BigDecimal#to_s(“F”) вместо него.

require 'bigdecimal/util'

d = BigDecimal("3.14")
d.to_digits                  # => "3.14"
to_f() Показать исходный код
static VALUE
BigDecimal_to_f(VALUE self)
{
    ENTER(1);
    Real *p;
    double d;
    SIGNED_VALUE e;
    char *buf;
    volatile VALUE str;

    GUARD_OBJ(p, GetVpValue(self, 1));
    if (VpVtoD(&d, &e, p) != 1)
        return rb_float_new(d);
    if (e > (SIGNED_VALUE)(DBL_MAX_10_EXP+BASE_FIG))
        goto overflow;
    if (e < (SIGNED_VALUE)(DBL_MIN_10_EXP-BASE_FIG))
        goto underflow;

    str = rb_str_new(0, VpNumOfChars(p, "E"));
    buf = RSTRING_PTR(str);
    VpToString(p, buf, RSTRING_LEN(str), 0, 0);
    errno = 0;
    d = strtod(buf, 0);
    if (errno == ERANGE) {
        if (d == 0.0) goto underflow;
        if (fabs(d) >= HUGE_VAL) goto overflow;
    }
    return rb_float_new(d);

overflow:
    VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
    if (BIGDECIMAL_NEGATIVE_P(p))
        return rb_float_new(VpGetDoubleNegInf());
    else
        return rb_float_new(VpGetDoublePosInf());

underflow:
    VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
    if (BIGDECIMAL_NEGATIVE_P(p))
        return rb_float_new(-0.0);
    else
        return rb_float_new(0.0);
}

Возвращает новый объект Float с приблизительно таким же значением, что и число BigDecimal. Применяются обычные ограничения точности и встроенные ошибки двоичной арифметики Float.

to_i() Показать исходный код
static VALUE
BigDecimal_to_i(VALUE self)
{
    ENTER(5);
    ssize_t e, nf;
    Real *p;

    GUARD_OBJ(p, GetVpValue(self, 1));
    BigDecimal_check_num(p);

    e = VpExponent10(p);
    if (e <= 0) return INT2FIX(0);
    nf = VpBaseFig();
    if (e <= nf) {
        return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0]));
    }
    else {
        VALUE a = BigDecimal_split(self);
        VALUE digits = RARRAY_AREF(a, 1);
        VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
        VALUE ret;
        ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);

        if (BIGDECIMAL_NEGATIVE_P(p)) {
            numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
        }
        if (dpower < 0) {
            ret = rb_funcall(numerator, rb_intern("div"), 1,
                              rb_funcall(INT2FIX(10), rb_intern("**"), 1,
                                         INT2FIX(-dpower)));
        }
        else {
            ret = rb_funcall(numerator, '*', 1,
                             rb_funcall(INT2FIX(10), rb_intern("**"), 1,
                                        INT2FIX(dpower)));
        }
        if (RB_TYPE_P(ret, T_FLOAT)) {
            rb_raise(rb_eFloatDomainError, "Infinity");
        }
        return ret;
    }
}

Возвращает значение в виде Integer.

Если BigDecimal равен бесконечности или NaN, генерирует исключение FloatDomainError.

Также переименовано в: to_int
to_int()

Возвращает значение в виде Integer.

Если BigDecimal равен бесконечности или NaN, генерирует исключение FloatDomainError.

Псевдоним для: to_i
to_json(*args) Показать исходный код
# File ext/json/lib/json/add/bigdecimal.rb, line 55
def to_json(*args)
  as_json.to_json(*args)
end

Возвращает строку JSON, представляющую self:

require 'json/add/bigdecimal'
puts BigDecimal(2).to_json
puts BigDecimal(2.0, 4).to_json
puts BigDecimal(Complex(2, 0)).to_json

Вывод:

{"json_class":"BigDecimal","b":"27:0.2e1"}
{"json_class":"BigDecimal","b":"36:0.2e1"}
{"json_class":"BigDecimal","b":"27:0.2e1"}
to_r() Показать исходный код
static VALUE
BigDecimal_to_r(VALUE self)
{
    Real *p;
    ssize_t sign, power, denomi_power;
    VALUE a, digits, numerator;

    p = GetVpValue(self, 1);
    BigDecimal_check_num(p);

    sign = VpGetSign(p);
    power = VpExponent10(p);
    a = BigDecimal_split(self);
    digits = RARRAY_AREF(a, 1);
    denomi_power = power - RSTRING_LEN(digits);
    numerator = rb_funcall(digits, rb_intern("to_i"), 0);

    if (sign < 0) {
        numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
    }
    if (denomi_power < 0) {
        return rb_Rational(numerator,
                           rb_funcall(INT2FIX(10), rb_intern("**"), 1,
                                      INT2FIX(-denomi_power)));
    }
    else {
        return rb_Rational1(rb_funcall(numerator, '*', 1,
                                       rb_funcall(INT2FIX(10), rb_intern("**"), 1,
                                                  INT2FIX(denomi_power))));
    }
}

Преобразует BigDecimal в Rational.

to_s(s) Показать исходный код
static VALUE
BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
{
    ENTER(5);
    int   fmt = 0;   /* 0: E format, 1: F format */
    int   fPlus = 0; /* 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
    Real  *vp;
    volatile VALUE str;
    char  *psz;
    char   ch;
    size_t nc, mc = 0;
    SIGNED_VALUE m;
    VALUE  f;

    GUARD_OBJ(vp, GetVpValue(self, 1));

    if (rb_scan_args(argc, argv, "01", &f) == 1) {
        if (RB_TYPE_P(f, T_STRING)) {
            psz = StringValueCStr(f);
            if (*psz == ' ') {
                fPlus = 1;
                psz++;
            }
            else if (*psz == '+') {
                fPlus = 2;
                psz++;
            }
            while ((ch = *psz++) != 0) {
                if (ISSPACE(ch)) {
                    continue;
                }
                if (!ISDIGIT(ch)) {
                    if (ch == 'F' || ch == 'f') {
                        fmt = 1; /* F format */
                    }
                    break;
                }
                mc = mc*10 + ch - '0';
            }
        }
        else {
            m = NUM2INT(f);
            if (m <= 0) {
                rb_raise(rb_eArgError, "argument must be positive");
            }
            mc = (size_t)m;
        }
    }
    if (fmt) {
        nc = VpNumOfChars(vp, "F");
    }
    else {
        nc = VpNumOfChars(vp, "E");
    }
    if (mc > 0) {
        nc += (nc + mc - 1) / mc + 1;
    }

    str = rb_usascii_str_new(0, nc);
    psz = RSTRING_PTR(str);

    if (fmt) {
        VpToFString(vp, psz, RSTRING_LEN(str), mc, fPlus);
    }
    else {
        VpToString (vp, psz, RSTRING_LEN(str), mc, fPlus);
    }
    rb_str_resize(str, strlen(psz));
    return str;
}

Преобразует значение в строку.

Формат по умолчанию похож на 0.xxxxEnn.

Необязательный параметр s состоит либо из целого числа; либо из необязательного «+» или « », за которым необязательно следует число, за которым необязательно следует «E» или «F».

Если в начале s стоит «+», положительные значения возвращаются с ведущим «+».

Пробел в начале s возвращает положительные значения с ведущим пробелом.

Если s содержит число, пробел вставляется после каждой группы из этого числа цифр, начиная с «.» и считая наружу.

Если s заканчивается на «E», используется инженерная нотация (0.xxxxEnn).

Если s заканчивается на «F», используется обычная нотация чисел с плавающей запятой.

Примеры:

BigDecimal('-1234567890123.45678901234567890').to_s('5F')
  #=> '-123 45678 90123.45678 90123 45678 9'

BigDecimal('1234567890123.45678901234567890').to_s('+8F')
  #=> '+12345 67890123.45678901 23456789'

BigDecimal('1234567890123.45678901234567890').to_s(' F')
  #=> ' 1234567890123.4567890123456789'
truncate(n) Показать исходный код
static VALUE
BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
{
    ENTER(5);
    Real *c, *a;
    int iLoc;
    VALUE vLoc;
    size_t mx, pl = VpSetPrecLimit(0);

    if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
        iLoc = 0;
    }
    else {
        iLoc = NUM2INT(vLoc);
    }

    GUARD_OBJ(a, GetVpValue(self, 1));
    mx = a->Prec * (VpBaseFig() + 1);
    GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
    VpSetPrecLimit(pl);
    VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
    if (argc == 0) {
        return BigDecimal_to_i(VpCheckGetValue(c));
    }
    return VpCheckGetValue(c);
}

Округляет до ближайшего целого числа (по умолчанию), возвращая результат как BigDecimal.

BigDecimal('3.14159').truncate #=> 3
BigDecimal('8.7').truncate #=> 8
BigDecimal('-9.9').truncate #=> -9

Если n указан и положителен, дробная часть результата не имеет более, чем указанное количество цифр.

Если n указан и отрицателен, по крайней мере, указанное количество цифр слева от десятичной точки будет равно 0 в результате.

BigDecimal('3.14159').truncate(3) #=> 3.141
BigDecimal('13345.234').truncate(-2) #=> 13300.0
zero?() Показать исходный код
static VALUE
BigDecimal_zero(VALUE self)
{
    Real *a = GetVpValue(self, 1);
    return VpIsZero(a) ? Qtrue : Qfalse;
}

Возвращает True, если значение равно нулю.

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

Spec-Zone.ru

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