[前][次][番号順一覧][スレッド一覧]

ruby-changes:21137

From: marcandre <ko1@a...>
Date: Mon, 5 Sep 2011 05:14:36 +0900 (JST)
Subject: [ruby-changes:21137] marcandRe: r33186 (trunk): * numeric.c (flo_round): Make Float#round round big values [bug #5272]

marcandre	2011-09-05 05:14:29 +0900 (Mon, 05 Sep 2011)

  New Revision: 33186

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=33186

  Log:
    * numeric.c (flo_round): Make Float#round round big values [bug #5272]

  Modified files:
    trunk/ChangeLog
    trunk/numeric.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 33185)
+++ ChangeLog	(revision 33186)
@@ -1,3 +1,8 @@
+Mon Sep  5 05:13:22 2011  Marc-Andre Lafortune  <ruby-core@m...>
+
+	* numeric.c (flo_round): Make Float#round round big values [bug
+	  #5272]
+
 Mon Sep  5 04:28:25 2011  Marc-Andre Lafortune  <ruby-core@m...>
 
 	* numeric.c (int_round): Integer#round always returns an Integer [Bug
Index: numeric.c
===================================================================
--- numeric.c	(revision 33185)
+++ numeric.c	(revision 33186)
@@ -1494,6 +1494,9 @@
     return n;
 }
 
+static VALUE
+flo_truncate(VALUE num);
+
 /*
  *  call-seq:
  *     flt.round([ndigits])  ->  integer or float
@@ -1531,13 +1534,18 @@
     double number, f;
     int ndigits = 0;
     int binexp;
-    long val;
     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}",
@@ -1557,41 +1565,15 @@
 	So if ndigits + binexp/(4 or 3) >= float_dig, the result is number
 	If ndigits + binexp/(3 or 4) < 0 the result is 0
 */
-    if (isinf(number) || isnan(number)) {
-	/* Do nothing */
+    if (isinf(number) || isnan(number) ||
+	(((long)ndigits - float_dig) * (3 + (binexp > 0)) + binexp >= 0)) {
+	return num;
     }
-    else if ((long)ndigits * (4 - (binexp > 0)) + binexp < 0) {
-	number = 0;
+    if ((long)ndigits * (4 - (binexp > 0)) + binexp < 0) {
+	return DBL2NUM(0);
     }
-    else if (((long)ndigits - float_dig) * (3 + (binexp > 0)) + binexp < 0) {
-	f = pow(10, abs(ndigits));
-	if (ndigits < 0) {
-	    double absnum = fabs(number);
-	    if (absnum < f) return INT2FIX(0);
-	    if (!FIXABLE(number)) {
-		VALUE f10 = int_pow(10, -ndigits);
-		VALUE n10 = f10;
-		if (number < 0) {
-		    f10 = FIXNUM_P(f10) ? fix_uminus(f10) : rb_big_uminus(f10);
-		}
-		num = rb_big_idiv(rb_dbl2big(absnum), n10);
-		return FIXNUM_P(num) ? fix_mul(num, f10) : rb_big_mul(num, f10);
-	    }
-	    number /= f;
-	}
-	else number *= f;
-	number = round(number);
-	if (ndigits < 0) number *= f;
-	else number /= f;
-    }
-
-    if (ndigits > 0) return DBL2NUM(number);
-
-    if (!FIXABLE(number)) {
-	return rb_dbl2big(number);
-    }
-    val = (long)number;
-    return LONG2FIX(val);
+    f = pow(10, ndigits);
+    return DBL2NUM(round(number * f) / f);
 }
 
 /*

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]