[ruby/bigdecimal] Let BigDecimal_DoDivmod use the same precision calculation as BigDecimal_divide
https://github.com/ruby/bigdecimal/commit/11cb2c8840
This commit is contained in:
parent
e1265c8198
commit
7b2cfce543
@ -1613,26 +1613,33 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
mx = a->Prec + vabs(a->exponent);
|
||||
if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
|
||||
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);
|
||||
mx = c->Prec * (VpBaseFig() + 1);
|
||||
|
||||
mx = c->Prec * BASE_FIG;
|
||||
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
||||
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
|
||||
|
||||
VpMult(res, d, b);
|
||||
VpAddSub(c, a, res, -1);
|
||||
|
||||
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
|
||||
VpAddSub(res, d, VpOne(), -1);
|
||||
/* remainder adjustment for negative case */
|
||||
VpAddSub(res, d, VpOne(), -1);
|
||||
GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0", true));
|
||||
VpAddSub(d, c, b, 1);
|
||||
*div = res;
|
||||
*mod = d;
|
||||
} else {
|
||||
*div = d;
|
||||
*mod = c;
|
||||
VpAddSub(d, c, b, 1);
|
||||
*div = res;
|
||||
*mod = d;
|
||||
}
|
||||
else {
|
||||
*div = d;
|
||||
*mod = c;
|
||||
}
|
||||
return Qtrue;
|
||||
|
||||
|
@ -1043,6 +1043,13 @@ class TestBigDecimal < Test::Unit::TestCase
|
||||
assert_raise(ZeroDivisionError){BigDecimal("0").divmod(0)}
|
||||
end
|
||||
|
||||
def test_divmod_precision
|
||||
a = BigDecimal('2e55')
|
||||
b = BigDecimal('1.23456789e10')
|
||||
q, r = a.divmod(b)
|
||||
assert_equal((a/b), q)
|
||||
end
|
||||
|
||||
def test_divmod_error
|
||||
assert_raise(TypeError) { BigDecimal(20).divmod('2') }
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user