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:
Return the modulo after division of flt
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)); }
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, '*'); } }
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("**")); } }
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, '+'); } }
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, '-'); } }
Returns float, negated.
static VALUE flo_uminus(VALUE flt) { return DBL2NUM(-RFLOAT_VALUE(flt)); }
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, '/'); } }
true
if flt
is less than real
.
static VALUE flo_lt(VALUE x, VALUE y) { double a, b; a = RFLOAT_VALUE(x); switch (TYPE(y)) { case T_FIXNUM: b = (double)FIX2LONG(y); break; case T_BIGNUM: b = rb_big2dbl(y); break; 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; }
true
if flt
is less than or equal to
real
.
static VALUE flo_le(VALUE x, VALUE y) { double a, b; a = RFLOAT_VALUE(x); switch (TYPE(y)) { case T_FIXNUM: b = (double)FIX2LONG(y); break; case T_BIGNUM: b = rb_big2dbl(y); break; 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; }
Returns -1, 0, +1 or nil depending on whether flt is less than,
equal to, or greater than real. This is the basis for the tests in
Comparable
.
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: b = (double)FIX2LONG(y); break; case T_BIGNUM: if (isinf(a)) { if (a > 0.0) return INT2FIX(1); else return INT2FIX(-1); } b = rb_big2dbl(y); break; 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); }
Returns true
only if obj has the same value as
flt. Contrast this with Float#eql?
, which requires
obj to be a Float
.
1.0 == 1 #=> true
static VALUE flo_eq(VALUE x, VALUE y) { volatile double a, b; switch (TYPE(y)) { case T_FIXNUM: b = (double)FIX2LONG(y); break; case T_BIGNUM: b = rb_big2dbl(y); break; 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; }
Returns true
only if obj has the same value as
flt. Contrast this with Float#eql?
, which requires
obj to be a Float
.
1.0 == 1 #=> true
static VALUE flo_eq(VALUE x, VALUE y) { volatile double a, b; switch (TYPE(y)) { case T_FIXNUM: b = (double)FIX2LONG(y); break; case T_BIGNUM: b = rb_big2dbl(y); break; 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; }
true
if flt
is greater than real
.
static VALUE flo_gt(VALUE x, VALUE y) { double a, b; a = RFLOAT_VALUE(x); switch (TYPE(y)) { case T_FIXNUM: b = (double)FIX2LONG(y); break; case T_BIGNUM: b = rb_big2dbl(y); break; 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; }
true
if flt
is greater than or equal to
real
.
static VALUE flo_ge(VALUE x, VALUE y) { double a, b; a = RFLOAT_VALUE(x); switch (TYPE(y)) { case T_FIXNUM: b = (double)FIX2LONG(y); break; case T_BIGNUM: b = rb_big2dbl(y); break; 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; }
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); }
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); }
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); }
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); }
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); }
See Numeric#divmod
.
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); }
Returns true
only if obj is a Float
with
the same value as flt. Contrast this with Float#==
,
which performs type conversions.
1.0.eql?(1) #=> false
static VALUE flo_eql(VALUE x, VALUE y) { if (TYPE(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; }
Returns float / numeric.
static VALUE flo_quo(VALUE x, VALUE y) { return rb_funcall(x, '/', 1, y); }
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_FINITE if (!finite(value)) return Qfalse; #else if (isinf(value) || isnan(value)) return Qfalse; #endif return Qtrue; }
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); }
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); }
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; }
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); }
Return the modulo after division of flt
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)); }
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; }
Returns the numerator. The result is machine dependent.
For example:
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); }
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); }
Returns float / numeric.
static VALUE flo_quo(VALUE x, VALUE y) { return rb_funcall(x, '/', 1, y); }
Returns a simpler approximation of the value (flt-|eps| <= result <= flt+|eps|). if eps is not given, it will be chosen automatically.
For example:
0.3.rationalize #=> (3/10) 1.333.rationalize #=> (1333/1000) 1.333.rationalize(0.01) #=> (4/3)
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 a = rb_rational_new2(f_sub(f_mul(TWO, f), ONE), f_lshift(ONE, f_sub(ONE, n))); b = rb_rational_new2(f_add(f_mul(TWO, f), ONE), f_lshift(ONE, f_sub(ONE, n))); #else a = rb_rational_new2(f_sub(f_mul(INT2FIX(FLT_RADIX), f), INT2FIX(FLT_RADIX - 1)), f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n))); b = rb_rational_new2(f_add(f_mul(INT2FIX(FLT_RADIX), f), INT2FIX(FLT_RADIX - 1)), f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n))); #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); }
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); }
As flt
is already a float, returns self
.
static VALUE flo_to_f(VALUE num) { return num; }
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); }
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); }
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.
For example:
2.0.to_r #=> (2/1) 2.5.to_r #=> (5/2) -0.75.to_r #=> (-3/4) 0.0.to_r #=> (0/1)
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 }
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 - digs < float_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; }
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); }
Commenting is here to help enhance the documentation. For example, sample code, 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.