[gnc-numeric.hpp] Keep the sign and leading zeroes in decimal output

operator<< printed the integer and fractional parts with separate
integer divisions, so 5/100 came out as "0.5", 105/100 as "1.5" and
-1/100 as "0.1": leading zeroes of the fraction were dropped and values
between -1 and 0 lost their sign. Print the magnitude and write each
fractional digit so the output matches the value.
This commit is contained in:
Ryan Duguid committed 2026-10-30 08:44:27 +11:00
1 parent 1283b34811
commit 3b80f573ee
2 files changed
+36 -2

No files matched your search

+13 -2
View File
@@ -363,8 +363,19 @@ std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>&
if (n.denom() == 1)
ss << n.num();
else if (n.is_decimal())
ss << n.num() / n.denom() << dec_pt
<< (n.num() > 0 ? n.num() : -n.num()) % n.denom();
{
/* Use the magnitude so that values between -1 and 0 keep their sign,
* and write each fractional digit so that leading zeroes are kept. */
auto num = n.num();
auto mag = num < 0 ? 0 - static_cast<uint64_t>(num)
: static_cast<uint64_t>(num);
auto den = static_cast<uint64_t>(n.denom());
if (num < 0)
ss << static_cast<charT>('-');
ss << mag / den << dec_pt;
for (auto place = den / 10; place > 0; place /= 10)
ss << static_cast<charT>('0' + mag % den / place % 10);
}
else
ss << n.num() << "/" << n.denom();
s << ss.str();
@@ -328,6 +328,29 @@ TEST(gncnumeric_stream, output_stream)
EXPECT_EQ("123/456", output.str());
}
TEST(gncnumeric_stream, output_stream_decimal_places)
{
std::ostringstream output;
output << GncNumeric(5, 100);
EXPECT_EQ("0.05", output.str());
output.str("");
output << GncNumeric(105, 100);
EXPECT_EQ("1.05", output.str());
output.str("");
output << GncNumeric(-105, 100);
EXPECT_EQ("-1.05", output.str());
output.str("");
output << GncNumeric(-1, 100);
EXPECT_EQ("-0.01", output.str());
output.str("");
output << GncNumeric(-5, 10);
EXPECT_EQ("-0.5", output.str());
output.str("");
output << GncNumeric(INT64_MIN, 1000);
EXPECT_EQ("-9223372036854775.808", output.str());
EXPECT_EQ("0.007", GncNumeric(7, 1000).to_string());
}
TEST(gncnumeric_stream, input_stream)
{
std::istringstream input("123456");