In Files

  • complex.c
  • numeric.c
  • rational.c
toggle debugging

Float

Float objects represent inexact real numbers using the native architecture's double-precision floating point representation.

Floating point has a different arithmetic and is a inexact number. So you should know its esoteric system. see following:

Constants

DIG

The number of decimal digits in a double-precision floating point.

Usually defaults to 15.

EPSILON

The difference between 1 and the smallest double-precision floating point number.

Usually defaults to 2.2204460492503131e-16.

INFINITY

An expression representing positive infinity.

MANT_DIG

The number of base digits for the double data type.

Usually defaults to 53.

MAX

The largest possible integer in a double-precision floating point number.

Usually defaults to 1.7976931348623157e+308.

MAX_10_EXP

The largest positive exponent in a double-precision floating point where 10 raised to this power minus 1.

Usually defaults to 308.

MAX_EXP

The largest possible exponent value in a double-precision floating point.

Usually defaults to 1024.

MIN

The smallest positive integer in a double-precision floating point.

Usually defaults to 2.2250738585072014e-308.

MIN_10_EXP

The smallest negative exponent in a double-precision floating point where 10 raised to this power minus 1.

Usually defaults to -307.

MIN_EXP

The smallest posable exponent value in a double-precision floating point.

Usually defaults to -1021.

NAN

An expression representing a value which is “not a number”.

RADIX

The base of the floating point, or number of unique digits used to represent the number.

Usually defaults to 2 on most systems, which would represent a base-10 decimal.

ROUNDS

Represents the rounding mode for floating point addition.

Usually defaults to 1, rounding to the nearest number.

Other modes include:

-1

Indeterminable

0

Rounding towards zero

1

Rounding to the nearest number

2

Rounding towards positive infinity

3

Rounding towards negative infinity

Public Instance Methods

float % other → float click to toggle source

Return the modulo after division of float by other.

6543.21.modulo(137)      #=> 104.21
6543.21.modulo(137.24)   #=> 92.9299999999996
 
               static VALUE
flo_mod(VALUE x, VALUE y)
{
    double fy;

    switch (TYPE(y)) {
      case T_FIXNUM:
        fy = (double)FIX2LONG(y);
        break;
      case T_BIGNUM:
        fy = rb_big2dbl(y);
        break;
      case T_FLOAT:
        fy = RFLOAT_VALUE(y);
        break;
      default:
        return rb_num_coerce_bin(x, y, '%');
    }
    return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(x), fy));
}
            
float * other → float click to toggle source

Returns a new float which is the product of float and other.

 
               static VALUE
flo_mul(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        return DBL2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y));
      case T_BIGNUM:
        return DBL2NUM(RFLOAT_VALUE(x) * rb_big2dbl(y));
      case T_FLOAT:
        return DBL2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '*');
    }
}
            
flt ** other → float click to toggle source

Raises float the other power.

2.0**3      #=> 8.0
 
               static VALUE
flo_pow(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        return DBL2NUM(pow(RFLOAT_VALUE(x), (double)FIX2LONG(y)));
      case T_BIGNUM:
        return DBL2NUM(pow(RFLOAT_VALUE(x), rb_big2dbl(y)));
      case T_FLOAT:
        {
            double dx = RFLOAT_VALUE(x);
            double dy = RFLOAT_VALUE(y);
            if (dx < 0 && dy != round(dy))
                return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
            return DBL2NUM(pow(dx, dy));
        }
      default:
        return rb_num_coerce_bin(x, y, rb_intern("**"));
    }
}
            
float + other → float click to toggle source

Returns a new float which is the sum of float and other.

 
               static VALUE
flo_plus(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
      case T_BIGNUM:
        return DBL2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y));
      case T_FLOAT:
        return DBL2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '+');
    }
}
            
float - other → float click to toggle source

Returns a new float which is the difference of float and other.

 
               static VALUE
flo_minus(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
      case T_BIGNUM:
        return DBL2NUM(RFLOAT_VALUE(x) - rb_big2dbl(y));
      case T_FLOAT:
        return DBL2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '-');
    }
}
            
-float → float click to toggle source

Returns float, negated.

 
               static VALUE
flo_uminus(VALUE flt)
{
    return DBL2NUM(-RFLOAT_VALUE(flt));
}
            
float / other → float click to toggle source

Returns a new float which is the result of dividing float by other.

 
               static VALUE
flo_div(VALUE x, VALUE y)
{
    long f_y;
    double d;

    switch (TYPE(y)) {
      case T_FIXNUM:
        f_y = FIX2LONG(y);
        return DBL2NUM(RFLOAT_VALUE(x) / (double)f_y);
      case T_BIGNUM:
        d = rb_big2dbl(y);
        return DBL2NUM(RFLOAT_VALUE(x) / d);
      case T_FLOAT:
        return DBL2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '/');
    }
}
            
flt < real → true or false click to toggle source

true if flt is less than real. The result of NaN < NaN is undefined, so the implementation-dependent value is returned.

 
               static VALUE
flo_lt(VALUE x, VALUE y)
{
    double a, b;

    a = RFLOAT_VALUE(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return -FIX2INT(rel) < 0 ? Qtrue : Qfalse;
        return Qfalse;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;

      default:
        return rb_num_coerce_relop(x, y, '<');
    }
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a < b)?Qtrue:Qfalse;
}
            
flt <= real → true or false click to toggle source

true if flt is less than or equal to real. The result of NaN <= NaN is undefined, so the implementation-dependent value is returned.

 
               static VALUE
flo_le(VALUE x, VALUE y)
{
    double a, b;

    a = RFLOAT_VALUE(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return -FIX2INT(rel) <= 0 ? Qtrue : Qfalse;
        return Qfalse;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;

      default:
        return rb_num_coerce_relop(x, y, rb_intern("<="));
    }
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a <= b)?Qtrue:Qfalse;
}
            
float <=> real → -1, 0, +1 or nil click to toggle source

Returns -1, 0, +1 or nil depending on whether float is less than, equal to, or greater than real. This is the basis for the tests in Comparable.

The result of NaN <=> NaN is undefined, so the implementation-dependent value is returned.

nil is returned if the two values are incomparable.

 
               static VALUE
flo_cmp(VALUE x, VALUE y)
{
    double a, b;
    VALUE i;

    a = RFLOAT_VALUE(x);
    if (isnan(a)) return Qnil;
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return INT2FIX(-FIX2INT(rel));
        return rel;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
        break;

      default:
        if (isinf(a) && (i = rb_check_funcall(y, rb_intern("infinite?"), 0, 0)) != Qundef) {
            if (RTEST(i)) {
                int j = rb_cmpint(i, x, y);
                j = (a > 0.0) ? (j > 0 ? 0 : +1) : (j < 0 ? 0 : -1);
                return INT2FIX(j);
            }
            if (a > 0.0) return INT2FIX(1);
            return INT2FIX(-1);
        }
        return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
    }
    return rb_dbl_cmp(a, b);
}
            
flt == obj → true or false click to toggle source

Returns true only if obj has the same value as flt. Contrast this with Float#eql?, which requires obj to be a Float. The result of NaN == NaN is undefined, so the implementation-dependent value is returned.

1.0 == 1   #=> true
 
               static VALUE
flo_eq(VALUE x, VALUE y)
{
    volatile double a, b;

    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
        return rb_integer_float_eq(y, x);
      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;
      default:
        return num_equal(x, y);
    }
    a = RFLOAT_VALUE(x);
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a == b)?Qtrue:Qfalse;
}
            
flt == obj → true or false click to toggle source

Returns true only if obj has the same value as flt. Contrast this with Float#eql?, which requires obj to be a Float. The result of NaN == NaN is undefined, so the implementation-dependent value is returned.

1.0 == 1   #=> true
 
               static VALUE
flo_eq(VALUE x, VALUE y)
{
    volatile double a, b;

    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
        return rb_integer_float_eq(y, x);
      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;
      default:
        return num_equal(x, y);
    }
    a = RFLOAT_VALUE(x);
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a == b)?Qtrue:Qfalse;
}
            
flt > real → true or false click to toggle source

true if flt is greater than real. The result of NaN > NaN is undefined, so the implementation-dependent value is returned.

 
               static VALUE
flo_gt(VALUE x, VALUE y)
{
    double a, b;

    a = RFLOAT_VALUE(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return -FIX2INT(rel) > 0 ? Qtrue : Qfalse;
        return Qfalse;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;

      default:
        return rb_num_coerce_relop(x, y, '>');
    }
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a > b)?Qtrue:Qfalse;
}
            
flt >= real → true or false click to toggle source

true if flt is greater than or equal to real. The result of NaN >= NaN is undefined, so the implementation-dependent value is returned.

 
               static VALUE
flo_ge(VALUE x, VALUE y)
{
    double a, b;

    a = RFLOAT_VALUE(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return -FIX2INT(rel) >= 0 ? Qtrue : Qfalse;
        return Qfalse;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;

      default:
        return rb_num_coerce_relop(x, y, rb_intern(">="));
    }
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a >= b)?Qtrue:Qfalse;
}
            
abs → float click to toggle source

Returns the absolute value of flt.

(-34.56).abs   #=> 34.56
-34.56.abs     #=> 34.56
 
               static VALUE
flo_abs(VALUE flt)
{
    double val = fabs(RFLOAT_VALUE(flt));
    return DBL2NUM(val);
}
            
angle → 0 or float click to toggle source

Returns 0 if the value is positive, pi otherwise.

 
               static VALUE
float_arg(VALUE self)
{
    if (isnan(RFLOAT_VALUE(self)))
        return self;
    if (f_tpositive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
            
arg → 0 or float click to toggle source

Returns 0 if the value is positive, pi otherwise.

 
               static VALUE
float_arg(VALUE self)
{
    if (isnan(RFLOAT_VALUE(self)))
        return self;
    if (f_tpositive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
            
ceil → integer click to toggle source

Returns the smallest Integer greater than or equal to flt.

1.2.ceil      #=> 2
2.0.ceil      #=> 2
(-1.2).ceil   #=> -1
(-2.0).ceil   #=> -2
 
               static VALUE
flo_ceil(VALUE num)
{
    double f = ceil(RFLOAT_VALUE(num));
    long val;

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
            
coerce(numeric) → array click to toggle source

Returns an array with both aNumeric and flt represented as Float objects. This is achieved by converting aNumeric to a Float.

1.2.coerce(3)       #=> [3.0, 1.2]
2.5.coerce(1.1)     #=> [1.1, 2.5]
 
               static VALUE
flo_coerce(VALUE x, VALUE y)
{
    return rb_assoc_new(rb_Float(y), x);
}
            
denominator → integer click to toggle source

Returns the denominator (always positive). The result is machine dependent.

See numerator.

 
               static VALUE
float_denominator(VALUE self)
{
    double d = RFLOAT_VALUE(self);
    if (isinf(d) || isnan(d))
        return INT2FIX(1);
    return rb_call_super(0, 0);
}
            
divmod(numeric) → array click to toggle source

See Numeric#divmod.

42.0.divmod 6 #=> [7, 0.0]
42.0.divmod 5 #=> [8, 2.0]
 
               static VALUE
flo_divmod(VALUE x, VALUE y)
{
    double fy, div, mod;
    volatile VALUE a, b;

    switch (TYPE(y)) {
      case T_FIXNUM:
        fy = (double)FIX2LONG(y);
        break;
      case T_BIGNUM:
        fy = rb_big2dbl(y);
        break;
      case T_FLOAT:
        fy = RFLOAT_VALUE(y);
        break;
      default:
        return rb_num_coerce_bin(x, y, rb_intern("divmod"));
    }
    flodivmod(RFLOAT_VALUE(x), fy, &div, &mod);
    a = dbl2ival(div);
    b = DBL2NUM(mod);
    return rb_assoc_new(a, b);
}
            
eql?(obj) → true or false click to toggle source

Returns true only if obj is a Float with the same value as flt. Contrast this with Float#==, which performs type conversions. The result of NaN.eql?(NaN) is undefined, so the implementation-dependent value is returned.

1.0.eql?(1)   #=> false
 
               static VALUE
flo_eql(VALUE x, VALUE y)
{
    if (RB_TYPE_P(y, T_FLOAT)) {
        double a = RFLOAT_VALUE(x);
        double b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(a) || isnan(b)) return Qfalse;
#endif
        if (a == b)
            return Qtrue;
    }
    return Qfalse;
}
            
quo(numeric) → float click to toggle source

Returns float / numeric.

 
               static VALUE
flo_quo(VALUE x, VALUE y)
{
    return rb_funcall(x, '/', 1, y);
}
            
finite? → true or false click to toggle source

Returns true if flt is a valid IEEE floating point number (it is not infinite, and nan? is false).

 
               static VALUE
flo_is_finite_p(VALUE num)
{
    double value = RFLOAT_VALUE(num);

#if HAVE_ISFINITE
    if (!isfinite(value))
        return Qfalse;
#else
    if (isinf(value) || isnan(value))
        return Qfalse;
#endif

    return Qtrue;
}
            
floor → integer click to toggle source

Returns the largest integer less than or equal to flt.

1.2.floor      #=> 1
2.0.floor      #=> 2
(-1.2).floor   #=> -2
(-2.0).floor   #=> -2
 
               static VALUE
flo_floor(VALUE num)
{
    double f = floor(RFLOAT_VALUE(num));
    long val;

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
            
hash → integer click to toggle source

Returns a hash code for this float.

 
               static VALUE
flo_hash(VALUE num)
{
    double d;
    st_index_t hash;

    d = RFLOAT_VALUE(num);
    /* normalize -0.0 to 0.0 */
    if (d == 0.0) d = 0.0;
    hash = rb_memhash(&d, sizeof(d));
    return LONG2FIX(hash);
}
            
infinite? → nil, -1, +1 click to toggle source

Returns nil, -1, or +1 depending on whether flt is finite, -infinity, or +infinity.

(0.0).infinite?        #=> nil
(-1.0/0.0).infinite?   #=> -1
(+1.0/0.0).infinite?   #=> 1
 
               static VALUE
flo_is_infinite_p(VALUE num)
{
    double value = RFLOAT_VALUE(num);

    if (isinf(value)) {
        return INT2FIX( value < 0 ? -1 : 1 );
    }

    return Qnil;
}
            
inspect() click to toggle source
Alias for: to_s
magnitude → float click to toggle source

Returns the absolute value of flt.

(-34.56).abs   #=> 34.56
-34.56.abs     #=> 34.56
 
               static VALUE
flo_abs(VALUE flt)
{
    double val = fabs(RFLOAT_VALUE(flt));
    return DBL2NUM(val);
}
            
modulo(other) → float click to toggle source

Return the modulo after division of float by other.

6543.21.modulo(137)      #=> 104.21
6543.21.modulo(137.24)   #=> 92.9299999999996
 
               static VALUE
flo_mod(VALUE x, VALUE y)
{
    double fy;

    switch (TYPE(y)) {
      case T_FIXNUM:
        fy = (double)FIX2LONG(y);
        break;
      case T_BIGNUM:
        fy = rb_big2dbl(y);
        break;
      case T_FLOAT:
        fy = RFLOAT_VALUE(y);
        break;
      default:
        return rb_num_coerce_bin(x, y, '%');
    }
    return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(x), fy));
}
            
nan? → true or false click to toggle source

Returns true if flt is an invalid IEEE floating point number.

a = -1.0      #=> -1.0
a.nan?        #=> false
a = 0.0/0.0   #=> NaN
a.nan?        #=> true
 
               static VALUE
flo_is_nan_p(VALUE num)
{
    double value = RFLOAT_VALUE(num);

    return isnan(value) ? Qtrue : Qfalse;
}
            
numerator → integer click to toggle source

Returns the numerator. The result is machine dependent.

n = 0.3.numerator    #=> 5404319552844595
d = 0.3.denominator  #=> 18014398509481984
n.fdiv(d)            #=> 0.3
 
               static VALUE
float_numerator(VALUE self)
{
    double d = RFLOAT_VALUE(self);
    if (isinf(d) || isnan(d))
        return self;
    return rb_call_super(0, 0);
}
            
phase → 0 or float click to toggle source

Returns 0 if the value is positive, pi otherwise.

 
               static VALUE
float_arg(VALUE self)
{
    if (isnan(RFLOAT_VALUE(self)))
        return self;
    if (f_tpositive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
            
quo(numeric) → float click to toggle source

Returns float / numeric.

 
               static VALUE
flo_quo(VALUE x, VALUE y)
{
    return rb_funcall(x, '/', 1, y);
}
            
rationalize([eps]) → rational click to toggle source

Returns a simpler approximation of the value (flt-|eps| <= result <= flt+|eps|). if the optional eps is not given, it will be chosen automatically.

0.3.rationalize          #=> (3/10)
1.333.rationalize        #=> (1333/1000)
1.333.rationalize(0.01)  #=> (4/3)

See to_r.

 
               static VALUE
float_rationalize(int argc, VALUE *argv, VALUE self)
{
    VALUE e, a, b, p, q;

    if (f_negative_p(self))
        return f_negate(float_rationalize(argc, argv, f_abs(self)));

    rb_scan_args(argc, argv, "01", &e);

    if (argc != 0) {
        e = f_abs(e);
        a = f_sub(self, e);
        b = f_add(self, e);
    }
    else {
        VALUE f, n;

        float_decode_internal(self, &f, &n);
        if (f_zero_p(f) || f_positive_p(n))
            return rb_rational_new1(f_lshift(f, n));

#if FLT_RADIX == 2
        {
            VALUE two_times_f, den;

            two_times_f = f_mul(TWO, f);
            den = f_lshift(ONE, f_sub(ONE, n));

            a = rb_rational_new2(f_sub(two_times_f, ONE), den);
            b = rb_rational_new2(f_add(two_times_f, ONE), den);
        }
#else
        {
            VALUE radix_times_f, den;

            radix_times_f = f_mul(INT2FIX(FLT_RADIX), f);
            den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n));

            a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
            b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
        }
#endif
    }

    if (f_eqeq_p(a, b))
        return f_to_r(self);

    nurat_rationalize_internal(a, b, &p, &q);
    return rb_rational_new2(p, q);
}
            
round([ndigits]) → integer or float click to toggle source

Rounds flt to a given precision in decimal digits (default 0 digits). Precision may be negative. Returns a floating point number when ndigits is more than zero.

1.4.round      #=> 1
1.5.round      #=> 2
1.6.round      #=> 2
(-1.5).round   #=> -2

1.234567.round(2)  #=> 1.23
1.234567.round(3)  #=> 1.235
1.234567.round(4)  #=> 1.2346
1.234567.round(5)  #=> 1.23457

34567.89.round(-5) #=> 0
34567.89.round(-4) #=> 30000
34567.89.round(-3) #=> 35000
34567.89.round(-2) #=> 34600
34567.89.round(-1) #=> 34570
34567.89.round(0)  #=> 34568
34567.89.round(1)  #=> 34567.9
34567.89.round(2)  #=> 34567.89
34567.89.round(3)  #=> 34567.89
 
               static VALUE
flo_round(int argc, VALUE *argv, VALUE num)
{
    VALUE nd;
    double number, f;
    int ndigits = 0;
    int binexp;
    enum {float_dig = DBL_DIG+2};

    if (argc > 0 && rb_scan_args(argc, argv, "01", &nd) == 1) {
        ndigits = NUM2INT(nd);
    }
    if (ndigits < 0) {
        return int_round_0(flo_truncate(num), ndigits);
    }
    number  = RFLOAT_VALUE(num);
    if (ndigits == 0) {
        return dbl2ival(number);
    }
    frexp(number, &binexp);

/* Let `exp` be such that `number` is written as:"0.#{digits}e#{exp}",
   i.e. such that  10 ** (exp - 1) <= |number| < 10 ** exp
   Recall that up to float_dig digits can be needed to represent a double,
   so if ndigits + exp >= float_dig, the intermediate value (number * 10 ** ndigits)
   will be an integer and thus the result is the original number.
   If ndigits + exp <= 0, the result is 0 or "1e#{exp}", so
   if ndigits + exp < 0, the result is 0.
   We have:
        2 ** (binexp-1) <= |number| < 2 ** binexp
        10 ** ((binexp-1)/log_2(10)) <= |number| < 10 ** (binexp/log_2(10))
        If binexp >= 0, and since log_2(10) = 3.322259:
           10 ** (binexp/4 - 1) < |number| < 10 ** (binexp/3)
           floor(binexp/4) <= exp <= ceil(binexp/3)
        If binexp <= 0, swap the /4 and the /3
        So if ndigits + floor(binexp/(4 or 3)) >= float_dig, the result is number
        If ndigits + ceil(binexp/(3 or 4)) < 0 the result is 0
*/
    if (isinf(number) || isnan(number) ||
        (ndigits >= float_dig - (binexp > 0 ? binexp / 4 : binexp / 3 - 1))) {
        return num;
    }
    if (ndigits < - (binexp > 0 ? binexp / 3 + 1 : binexp / 4)) {
        return DBL2NUM(0);
    }
    f = pow(10, ndigits);
    return DBL2NUM(round(number * f) / f);
}
            
to_f → self click to toggle source

As flt is already a float, returns self.

 
               static VALUE
flo_to_f(VALUE num)
{
    return num;
}
            
to_i → integer click to toggle source
to_int → integer

Returns flt truncated to an Integer.

 
               static VALUE
flo_truncate(VALUE num)
{
    double f = RFLOAT_VALUE(num);
    long val;

    if (f > 0.0) f = floor(f);
    if (f < 0.0) f = ceil(f);

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
            
to_int → integer click to toggle source

Returns flt truncated to an Integer.

 
               static VALUE
flo_truncate(VALUE num)
{
    double f = RFLOAT_VALUE(num);
    long val;

    if (f > 0.0) f = floor(f);
    if (f < 0.0) f = ceil(f);

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
            
to_r → rational click to toggle source

Returns the value as a rational.

NOTE: 0.3.to_r isn’t the same as ‘0.3’.to_r. The latter is equivalent to ‘3/10’.to_r, but the former isn’t so.

2.0.to_r    #=> (2/1)
2.5.to_r    #=> (5/2)
-0.75.to_r  #=> (-3/4)
0.0.to_r    #=> (0/1)

See rationalize.

 
               static VALUE
float_to_r(VALUE self)
{
    VALUE f, n;

    float_decode_internal(self, &f, &n);
#if FLT_RADIX == 2
    {
        long ln = FIX2LONG(n);

        if (ln == 0)
            return f_to_r(f);
        if (ln > 0)
            return f_to_r(f_lshift(f, n));
        ln = -ln;
        return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln)));
    }
#else
    return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)));
#endif
}
            
to_s → string click to toggle source

Returns a string containing a representation of self. As well as a fixed or exponential form of the number, the call may return “NaN”, “Infinity”, and “-Infinity”.

 
               static VALUE
flo_to_s(VALUE flt)
{
    char *ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve);
    enum {decimal_mant = DBL_MANT_DIG-DBL_DIG};
    enum {float_dig = DBL_DIG+1};
    char buf[float_dig + (decimal_mant + CHAR_BIT - 1) / CHAR_BIT + 10];
    double value = RFLOAT_VALUE(flt);
    VALUE s;
    char *p, *e;
    int sign, decpt, digs;

    if (isinf(value))
        return rb_usascii_str_new2(value < 0 ? "-Infinity" : "Infinity");
    else if (isnan(value))
        return rb_usascii_str_new2("NaN");

    p = ruby_dtoa(value, 0, 0, &decpt, &sign, &e);
    s = sign ? rb_usascii_str_new_cstr("-") : rb_usascii_str_new(0, 0);
    if ((digs = (int)(e - p)) >= (int)sizeof(buf)) digs = (int)sizeof(buf) - 1;
    memcpy(buf, p, digs);
    xfree(p);
    if (decpt > 0) {
        if (decpt < digs) {
            memmove(buf + decpt + 1, buf + decpt, digs - decpt);
            buf[decpt] = '.';
            rb_str_cat(s, buf, digs + 1);
        }
        else if (decpt <= DBL_DIG) {
            long len;
            char *ptr;
            rb_str_cat(s, buf, digs);
            rb_str_resize(s, (len = RSTRING_LEN(s)) + decpt - digs + 2);
            ptr = RSTRING_PTR(s) + len;
            if (decpt > digs) {
                memset(ptr, '0', decpt - digs);
                ptr += decpt - digs;
            }
            memcpy(ptr, ".0", 2);
        }
        else {
            goto exp;
        }
    }
    else if (decpt > -4) {
        long len;
        char *ptr;
        rb_str_cat(s, "0.", 2);
        rb_str_resize(s, (len = RSTRING_LEN(s)) - decpt + digs);
        ptr = RSTRING_PTR(s);
        memset(ptr += len, '0', -decpt);
        memcpy(ptr -= decpt, buf, digs);
    }
    else {
      exp:
        if (digs > 1) {
            memmove(buf + 2, buf + 1, digs - 1);
        }
        else {
            buf[2] = '0';
            digs++;
        }
        buf[1] = '.';
        rb_str_cat(s, buf, digs + 1);
        rb_str_catf(s, "e%+03d", decpt - 1);
    }
    return s;
}
            
Also aliased as: inspect
truncate → integer click to toggle source

Returns flt truncated to an Integer.

 
               static VALUE
flo_truncate(VALUE num)
{
    double f = RFLOAT_VALUE(num);
    long val;

    if (f > 0.0) f = floor(f);
    if (f < 0.0) f = ceil(f);

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
            
zero? → true or false click to toggle source

Returns true if flt is 0.0.

 
               static VALUE
flo_zero_p(VALUE num)
{
    if (RFLOAT_VALUE(num) == 0.0) {
        return Qtrue;
    }
    return Qfalse;
}
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus