Make the GncNumeric string constructtor work for long decimal numbers.

It was failing to produce a correct representation for input with more than
14 digits after the decimal poin.  Fixes Bug 798916.  The bug was in
powten so this fix may corect other problems too.  For example conversion
of GncNumeric back to a string also failed in certain circumsances.
This commit is contained in:
Mike Alexander 2023-05-18 17:42:44 -04:00
parent d61b962954
commit 71afa3e0fc
3 changed files with 21 additions and 6 deletions

View File

@ -48,9 +48,9 @@ static const int64_t pten[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
INT64_C(10000000000), INT64_C(100000000000),
INT64_C(1000000000000), INT64_C(10000000000000),
INT64_C(100000000000000),
INT64_C(1000000000000000),
INT64_C(10000000000000000),
INT64_C(100000000000000000),
INT64_C(1000000000000000000)};
INT64_C(100000000000000000)};
#define POWTEN_OVERFLOW -5
int64_t
@ -175,9 +175,18 @@ GncNumeric::GncNumeric(const std::string& str, bool autoround)
GncInt128 high((neg && m[1].length() > 1) || (!neg && m[1].length()) ?
stoll(m[1].str()) : 0);
GncInt128 low(stoll(m[2].str()));
int64_t d = powten(m[2].str().length());
auto exp10 = m[2].str().length();
int64_t d = powten(exp10);
GncInt128 n = high * d + (neg ? -low : low);
while (exp10 > max_leg_digits)
{
/* If the arg to powten is bigger than max_leg_digits
it returns 10**max_leg_digits so reduce exp10 by
that amount */
n = n / powten(exp10 - max_leg_digits);
exp10 -= max_leg_digits;
}
if (!autoround && n.isBig())
{
std::ostringstream errmsg;

View File

@ -185,6 +185,12 @@ TEST(gncnumeric_constructors, test_string_constructor)
GncNumeric neg_decimal_frac_nozero("-.12345");
EXPECT_EQ(-12345, neg_decimal_frac_nozero.num());
EXPECT_EQ(100000, neg_decimal_frac_nozero.denom());
GncNumeric big_denom(".12345678901234567");
EXPECT_EQ(12345678901234567, big_denom.num());
EXPECT_EQ(100000000000000000, big_denom.denom());
GncNumeric too_big_denom(".123456789012345678");
EXPECT_EQ(12345678901234567, too_big_denom.num());
EXPECT_EQ(100000000000000000, too_big_denom.denom());
}
TEST(gncnumeric_output, string_output)

View File

@ -545,8 +545,8 @@ check_add_subtract (void)
static const gint64 pten[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000, 10000000000,
100000000000, 1000000000000, 10000000000000,
100000000000000, 10000000000000000,
100000000000000000, 1000000000000000000};
100000000000000, 1000000000000000,
10000000000000000, 100000000000000000};
#define POWTEN_OVERFLOW -5
static inline gint64