From 8b5b767465defd5326f92a0364252f80aa78bcfe Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 23 Jan 2023 21:28:10 -0500 Subject: [PATCH] AK: Print leading zeroes after the dot for FixedPoint numbers As a nearby comment says, "This is a terrible approximation". This doesn't make things less terrible, but it does make things more correct in the given framework of terribleness. Fixes #17156. --- AK/Format.cpp | 19 +++++++++++++++++-- Tests/AK/TestFixedPoint.cpp | 5 +++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/AK/Format.cpp b/AK/Format.cpp index 5f5b6cdfc7..20c08ac1be 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -389,6 +389,15 @@ ErrorOr FormatBuilder::put_fixed_point( auto fraction = (scale * fraction_value) / fraction_one; // TODO: overflows if (is_negative) fraction = scale - fraction; + + size_t leading_zeroes = 0; + { + auto scale_tmp = scale / 10; + for (; fraction < scale_tmp; ++leading_zeroes) { + scale_tmp /= 10; + } + } + while (fraction != 0 && fraction % 10 == 0) fraction /= 10; @@ -402,14 +411,20 @@ ErrorOr FormatBuilder::put_fixed_point( } } + if (visible_precision == 0) + leading_zeroes = 0; + if (zero_pad || visible_precision > 0) TRY(string_builder.try_append('.')); + if (leading_zeroes > 0) + TRY(format_builder.put_u64(0, base, false, false, true, Align::Right, leading_zeroes)); + if (visible_precision > 0) TRY(format_builder.put_u64(fraction, base, false, upper_case, true, Align::Right, visible_precision)); - if (zero_pad && (precision - visible_precision) > 0) - TRY(format_builder.put_u64(0, base, false, false, true, Align::Right, precision - visible_precision)); + if (zero_pad && (precision - leading_zeroes - visible_precision) > 0) + TRY(format_builder.put_u64(0, base, false, false, true, Align::Right, precision - leading_zeroes - visible_precision)); } TRY(put_string(string_builder.string_view(), align, min_width, NumericLimits::max(), fill)); diff --git a/Tests/AK/TestFixedPoint.cpp b/Tests/AK/TestFixedPoint.cpp index 9536926412..9628309abf 100644 --- a/Tests/AK/TestFixedPoint.cpp +++ b/Tests/AK/TestFixedPoint.cpp @@ -150,4 +150,9 @@ TEST_CASE(formatter) EXPECT_EQ(DeprecatedString::formatted("{}", FixedPoint<4>(123.456)), "123.4375"sv); EXPECT_EQ(DeprecatedString::formatted("{}", FixedPoint<4>(-123.456)), "-123.4375"sv); EXPECT_EQ(DeprecatedString::formatted("{}", FixedPoint<16> {}), "0"sv); + EXPECT_EQ(DeprecatedString::formatted("{}", FixedPoint<16>(0.1)), "0.09999"sv); + EXPECT_EQ(DeprecatedString::formatted("{}", FixedPoint<16>(0.02)), "0.019989"sv); + EXPECT_EQ(DeprecatedString::formatted("{}", FixedPoint<16>(0.003)), "0.00299"sv); + EXPECT_EQ(DeprecatedString::formatted("{}", FixedPoint<16>(0.0004)), "0.000396"sv); + EXPECT_EQ(DeprecatedString::formatted("{}", FixedPoint<16>(0.0000000005)), "0"sv); }