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

ruby-changes:70473

From: Kenta <ko1@a...>
Date: Fri, 24 Dec 2021 02:30:04 +0900 (JST)
Subject: [ruby-changes:70473] e1265c8198 (master): [ruby/bigdecimal] Use larger precision in divide for irrational or recurring results

https://git.ruby-lang.org/ruby.git/commit/?id=e1265c8198

From e1265c819870c6a4d6763529e9fbd2d70c722fe0 Mon Sep 17 00:00:00 2001
From: Kenta Murata <mrkn@m...>
Date: Fri, 22 Jan 2021 12:03:37 +0900
Subject: [ruby/bigdecimal] Use larger precision in divide for irrational or
 recurring results

Just in case for irrational or recurring results, the precision of the
quotient is set to at least more than 2*Float::DIG plus alpha.

[Bug #13754] [Fix GH-94]

https://github.com/ruby/bigdecimal/commit/99442c75d3
---
 ext/bigdecimal/bigdecimal.c        | 13 ++++++-------
 test/bigdecimal/test_bigdecimal.rb | 17 +++++++++++++++--
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 7cec33b7c94..71499a7a19f 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -1508,13 +1508,12 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1508
     SAVE(b);
 
     *div = b;
-    mx = a->Prec + vabs(a->exponent);
-    if (mx < b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
-    mx++; /* NOTE: An additional digit is needed for the compatibility to
-                   the version 1.2.1 and the former.  */
-    mx = (mx + 1) * VpBaseFig();
-    GUARD_OBJ((*c), VpCreateRbObject(mx, "#0", true));
-    GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true));
+    mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
+    mx *= BASE_FIG;
+    if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
+        mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
+    GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
+    GUARD_OBJ((*res), VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
     VpDivd(*c, *res, a, b);
     return Qnil;
 }
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index 1e6c59535fe..66b58aa1248 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -953,9 +953,13 @@ class TestBigDecimal < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/bigdecimal/test_bigdecimal.rb#L953
     assert_equal(2, BigDecimal("2") / 1)
     assert_equal(-2, BigDecimal("2") / -1)
 
-    assert_equal(BigDecimal('1486.868686869'), BigDecimal('1472.0') / BigDecimal('0.99'), '[ruby-core:59365] [#9316]')
+    assert_equal(BigDecimal('1486.868686869'),
+                 (BigDecimal('1472.0') / BigDecimal('0.99')).round(9),
+                 '[ruby-core:59365] [#9316]')
 
-    assert_equal(4.124045235, BigDecimal('0.9932') / (700 * BigDecimal('0.344045') / BigDecimal('1000.0')), '[#9305]')
+    assert_in_delta(4.124045235,
+                    (BigDecimal('0.9932') / (700 * BigDecimal('0.344045') / BigDecimal('1000.0'))).round(9, half: :up),
+                    10**Float::MIN_10_EXP, '[#9305]')
 
     BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
     assert_positive_zero(BigDecimal("1.0")  / BigDecimal("Infinity"))
@@ -969,6 +973,15 @@ class TestBigDecimal < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/bigdecimal/test_bigdecimal.rb#L973
     assert_raise_with_message(FloatDomainError, "Computation results in '-Infinity'") { BigDecimal("-1") / 0 }
   end
 
+  def test_dev_precision
+    bug13754 = '[ruby-core:82107] [Bug #13754]'
+    a = BigDecimal('101')
+    b = BigDecimal('0.9163472602589686')
+    c = a/b
+    assert(c.precision > b.precision,
+           "(101/0.9163472602589686).precision >= (0.9163472602589686).precision #{bug13754}")
+  end
+
   def test_div_with_float
     assert_kind_of(BigDecimal, BigDecimal("3") / 1.5)
     assert_equal(BigDecimal("0.5"), BigDecimal(1) / 2.0)
-- 
cgit v1.2.1


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

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