8000 Use larger precision in divide for irrational or recurring results · ruby/bigdecimal@99442c7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 99442c7

Browse files
committed
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]
1 parent eebc98b commit 99442c7

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

ext/bigdecimal/bigdecimal.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,13 +1508,12 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
15081508
SAVE(b);
15091509

15101510
*div = b;
1511-
mx = a->Prec + vabs(a->exponent);
1512-
if (mx < b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
1513-
mx++; /* NOTE: An additional digit is needed for the compatibility to
1514-
the version 1.2.1 and the former. */
1515-
mx = (mx + 1) * VpBaseFig();
1516-
GUARD_OBJ((*c), VpCreateRbObject(mx, "#0", true));
1517-
GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true));
1511+
mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
1512+
mx *= BASE_FIG;
1513+
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
1514+
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
1515+
GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
1516+
GUARD_OBJ((*res), VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
15181517
VpDivd(*c, *res, a, b);
15191518
return Qnil;
15201519
}

test/bigdecimal/test_bigdecimal.rb

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,9 +953,13 @@ def test_div
953953
assert_equal(2, BigDecimal("2") / 1)
954954
assert_equal(-2, BigDecimal("2") / -1)
955955

956-
assert_equal(BigDecimal('1486.868686869'), BigDecimal('1472.0') / BigDecimal('0.99'), '[ruby-core:59365] [#9316]')
956+
assert_equal(BigDecimal('1486.868686869'),
957+
(BigDecimal('1472.0') / BigDecimal('0.99')).round(9),
958+
'[ruby-core:59365] [#9316]')
957959

958-
assert_equal(4.124045235, BigDecimal('0.9932') / (700 * BigDecimal('0.344045') / BigDecimal('1000.0')), '[#9305]')
960+
assert_in_delta(4.124045235,
961+
(BigDecimal('0.9932') / (700 * BigDecimal('0.344045') / BigDecimal('1000.0'))).round(9, half: :up),
962+
10**Float::MIN_10_EXP, '[#9305]')
959963

960964
BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
961965
assert_positive_zero(BigDecimal("1.0") / BigDecimal("Infinity"))
@@ -969,6 +973,15 @@ def test_div
969973
assert_raise_with_message(FloatDomainError, "Computation results in '-Infinity'") { BigDecimal("-1") / 0 }
970974
end
971975

976+
def test_dev_precision
977+
bug13754 = '[ruby-core:82107] [Bug #13754]'
978+
a = BigDecimal('101')
979+
b = BigDecimal('0.9163472602589686')
980+
c = a/b
981+
assert(c.precision > b.precision,
982+
"(101/0.9163472602589686).precision >= (0.9163472602589686).precision #{bug13754}")
983+
end
984+
972985
def test_div_with_float
973986
assert_kind_of(BigDecimal, BigDecimal("3") / 1.5)
974987
assert_equal(BigDecimal("0.5"), BigDecimal(1) / 2.0)

0 commit comments

Comments
 (0)
0