Format: Strip trailing zeroes from floating point values

This is a pretty naive implementation that works well. The precision
parameter is interpreted as "maximum precision" instead of "minimum
precision", which in my opinion is the most useful interpretation.
This commit is contained in:
Jelle Raaijmakers 2021-04-08 18:50:56 +02:00 committed by Andreas Kling
parent 4bfd394384
commit c4e19250a1
2 changed files with 20 additions and 11 deletions

View file

@ -391,7 +391,6 @@ void FormatBuilder::put_f64(
FormatBuilder format_builder { string_builder };
format_builder.put_i64(static_cast<i64>(value), base, false, upper_case, false, Align::Right, 0, ' ', sign_mode);
string_builder.append('.');
if (precision > 0) {
// FIXME: This is a terrible approximation but doing it properly would be a lot of work. If someone is up for that, a good
@ -402,12 +401,22 @@ void FormatBuilder::put_f64(
if (value < 0)
value = -value;
for (u32 i = 0; i < precision; ++i)
value *= 10;
double epsilon = 0.5;
for (size_t i = 0; i < precision; ++i)
epsilon /= 10.0;
format_builder.put_u64(static_cast<u64>(value), base, false, upper_case, true, Align::Right, precision);
size_t visible_precision = 0;
for (; visible_precision < precision; ++visible_precision) {
if (value - static_cast<i64>(value) < epsilon)
break;
value *= 10.0;
epsilon *= 10.0;
}
// FIXME: Cut off trailing zeroes by default?
if (visible_precision > 0) {
string_builder.append('.');
format_builder.put_u64(static_cast<u64>(value), base, false, upper_case, true, Align::Right, visible_precision);
}
}
put_string(string_builder.string_view(), align, min_width, NumericLimits<size_t>::max(), fill);

View file

@ -252,11 +252,11 @@ TEST_CASE(file_descriptor)
TEST_CASE(floating_point_numbers)
{
EXPECT_EQ(String::formatted("{}", 1.12), "1.120000");
EXPECT_EQ(String::formatted("{}", 1.), "1.000000");
EXPECT_EQ(String::formatted("{:.3}", 1.12), "1.120");
EXPECT_EQ(String::formatted("{}", 1.12), "1.12");
EXPECT_EQ(String::formatted("{}", 1.), "1");
EXPECT_EQ(String::formatted("{:.3}", 1.12), "1.12");
EXPECT_EQ(String::formatted("{:.1}", 1.12), "1.1");
EXPECT_EQ(String::formatted("{}", -1.12), "-1.120000");
EXPECT_EQ(String::formatted("{}", -1.12), "-1.12");
// FIXME: There is always the question what we mean with the width field. Do we mean significant digits?
// Do we mean the whole width? This is what was the simplest to implement:
@ -265,12 +265,12 @@ TEST_CASE(floating_point_numbers)
TEST_CASE(no_precision_no_trailing_number)
{
EXPECT_EQ(String::formatted("{:.0}", 0.1), "0.");
EXPECT_EQ(String::formatted("{:.0}", 0.1), "0");
}
TEST_CASE(yay_this_implementation_sucks)
{
EXPECT_EQ(String::formatted("{:.0}", .99999999999), "0.");
EXPECT_EQ(String::formatted("{:.0}", .99999999999), "0");
}
TEST_CASE(format_nullptr)