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

ruby-changes:70491

From: Kenta <ko1@a...>
Date: Fri, 24 Dec 2021 02:30:31 +0900 (JST)
Subject: [ruby-changes:70491] a1d9fbef05 (master): [ruby/bigdecimal] Fix the result precision of BigDecimal#divmod

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

From a1d9fbef05fbf507b4c68cf3fbc50c6e27a3293e Mon Sep 17 00:00:00 2001
From: Kenta Murata <mrkn@m...>
Date: Fri, 24 Dec 2021 00:26:34 +0900
Subject: [ruby/bigdecimal] Fix the result precision of BigDecimal#divmod

https://github.com/ruby/bigdecimal/commit/a32f6cb9e2
---
 ext/bigdecimal/bigdecimal.c        | 21 +++++++++++++++++----
 test/bigdecimal/test_bigdecimal.rb |  6 ++++--
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 5af6c7c5bae..4111fbd7d32 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -1618,7 +1618,8 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1618
 /* For c = self.div(r): with round operation */
 {
     ENTER(5);
-    Real *a, *b;
+    Real *a, *b, *d;
+    ssize_t a_prec, b_prec;
     size_t mx;
 
     TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
@@ -1644,18 +1645,27 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1645
 
     TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
     SAVE(b);
-
     *div = b;
+
     mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
     mx *= BASE_FIG;
+
+    BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
+    BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
+    mx = (a_prec > b_prec) ? a_prec : b_prec;
+
     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;
 }
 
+static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod);
+
 /* call-seq:
  *   a / b   -> bigdecimal
  *
@@ -1736,6 +1746,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1746
     ENTER(8);
     Real *c=NULL, *d=NULL, *res=NULL;
     Real *a, *b;
+    ssize_t a_prec, b_prec;
     size_t mx;
 
     TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
@@ -1793,8 +1804,10 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1804
         return Qtrue;
     }
 
-    mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
-    mx *= BASE_FIG;
+    BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
+    BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
+
+    mx = (a_prec > b_prec) ? a_prec : b_prec;
     if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
         mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
 
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index bbfcbec4df6..825d7ec93f8 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -1047,11 +1047,13 @@ class TestBigDecimal < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/bigdecimal/test_bigdecimal.rb#L1047
     a = BigDecimal('2e55')
     b = BigDecimal('1.23456789e10')
     q, r = a.divmod(b)
-    assert_equal((a/b), q)
+    assert_equal((a/b).round(0, :down), q)
+    assert_equal((a - q*b), r)
 
     b = BigDecimal('-1.23456789e10')
     q, r = a.divmod(b)
-    assert_equal((a/b), q)
+    assert_equal((a/b).round(0, :down) - 1, q)
+    assert_equal((a - q*b), r)
   end
 
   def test_divmod_error
-- 
cgit v1.2.1


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

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