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

ruby-changes:21849

From: naruse <ko1@a...>
Date: Wed, 30 Nov 2011 02:41:04 +0900 (JST)
Subject: [ruby-changes:21849] naruse:r33898 (ruby_1_9_3): merge revision(s) 33158,33185,33186:

naruse	2011-11-30 02:39:36 +0900 (Wed, 30 Nov 2011)

  New Revision: 33898

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

  Log:
    merge revision(s) 33158,33185,33186:
    
    * numeric.c (flo_round): substitute machine dependent magic number.
    
    * numeric.c (flo_round): Make Float#round round big values [bug
      #5272]

  Modified files:
    branches/ruby_1_9_3/ChangeLog
    branches/ruby_1_9_3/numeric.c
    branches/ruby_1_9_3/test/ruby/test_float.rb
    branches/ruby_1_9_3/version.h

Index: ruby_1_9_3/ChangeLog
===================================================================
--- ruby_1_9_3/ChangeLog	(revision 33897)
+++ ruby_1_9_3/ChangeLog	(revision 33898)
@@ -1,3 +1,12 @@
+Wed Nov 30 02:37:32 2011  Marc-Andre Lafortune  <ruby-core@m...>
+
+	* numeric.c (flo_round): Make Float#round round big values [bug
+	  #5272]
+
+Wed Nov 30 02:37:32 2011  Nobuyoshi Nakada  <nobu@r...>
+
+	* numeric.c (flo_round): substitute machine dependent magic number.
+
 Wed Nov 30 02:28:22 2011  Marc-Andre Lafortune  <ruby-core@m...>
 
 	* numeric.c (int_round): Integer#round always returns an Integer [Bug
Index: ruby_1_9_3/numeric.c
===================================================================
--- ruby_1_9_3/numeric.c	(revision 33897)
+++ ruby_1_9_3/numeric.c	(revision 33898)
@@ -1494,6 +1494,9 @@
     return n;
 }
 
+static VALUE
+flo_truncate(VALUE num);
+
 /*
  *  call-seq:
  *     flt.round([ndigits])  ->  integer or float
@@ -1531,18 +1534,24 @@
     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);
-    frexp (number , &binexp);
+    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 17 digits can be needed to represent a double,
-   so if ndigits + exp >= 17, the intermediate value (number * 10 ** ndigits)
+   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.
@@ -1553,44 +1562,18 @@
 	   10 ** (binexp/4 - 1) < |number| < 10 ** (binexp/3)
 	   binexp/4 <= exp <= binexp/3
 	If binexp <= 0, swap the /4 and the /3
-	So if ndigits + binexp/(4 or 3) >= 17, the result is number
+	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 - 17) * (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);
 }
 
 /*
Index: ruby_1_9_3/version.h
===================================================================
--- ruby_1_9_3/version.h	(revision 33897)
+++ ruby_1_9_3/version.h	(revision 33898)
@@ -1,5 +1,5 @@
 #define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 1
+#define RUBY_PATCHLEVEL 2
 
 #define RUBY_RELEASE_DATE "2011-11-30"
 #define RUBY_RELEASE_YEAR 2011
Index: ruby_1_9_3/test/ruby/test_float.rb
===================================================================
--- ruby_1_9_3/test/ruby/test_float.rb	(revision 33897)
+++ ruby_1_9_3/test/ruby/test_float.rb	(revision 33898)
@@ -315,7 +315,9 @@
     assert_raise(FloatDomainError) { inf.ceil }
     assert_raise(FloatDomainError) { inf.round }
     assert_raise(FloatDomainError) { inf.truncate }
+  end
 
+  def test_round_with_precision
     assert_equal(1.100, 1.111.round(1))
     assert_equal(1.110, 1.111.round(2))
     assert_equal(11110.0, 11111.1.round(-1))
@@ -323,6 +325,17 @@
 
     assert_equal(10**300, 1.1e300.round(-300))
     assert_equal(-10**300, -1.1e300.round(-300))
+    assert_equal(1.0e-300, 1.1e-300.round(300))
+    assert_equal(-1.0e-300, -1.1e-300.round(300))
+
+    bug5227 = '[ruby-core:39093]'
+    assert_equal(42.0, 42.0.round(308), bug5227)
+    assert_equal(1.0e307, 1.0e307.round(2), bug5227)
+
+    assert_raise(TypeError) {1.0.round("4")}
+    assert_raise(TypeError) {1.0.round(nil)}
+    def (prec = Object.new).to_int; 2; end
+    assert_equal(1.0, 0.998.round(prec))
   end
 
   VS = [

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

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