diff --git a/libgnucash/engine/gnc-numeric.cpp b/libgnucash/engine/gnc-numeric.cpp index d0e716c295..7ab1ed2063 100644 --- a/libgnucash/engine/gnc-numeric.cpp +++ b/libgnucash/engine/gnc-numeric.cpp @@ -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; diff --git a/libgnucash/engine/test/gtest-gnc-numeric.cpp b/libgnucash/engine/test/gtest-gnc-numeric.cpp index e194367bbf..27b386748b 100644 --- a/libgnucash/engine/test/gtest-gnc-numeric.cpp +++ b/libgnucash/engine/test/gtest-gnc-numeric.cpp @@ -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) diff --git a/libgnucash/engine/test/test-numeric.cpp b/libgnucash/engine/test/test-numeric.cpp index 41ef28fa08..bf3cd51dd7 100644 --- a/libgnucash/engine/test/test-numeric.cpp +++ b/libgnucash/engine/test/test-numeric.cpp @@ -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