AK: Fix incorrect formatter signing of numbers between -1.0 and 0.0

Floating point numbers are casted to i64 and passed to the integer
formatting logic, and the floating point portion of the number is
handled separately. However, casting to i64 when the number is between
-1.0 and 0.0 produces 0, so the sign would be lost. This commit fixes
that by using put_u64 instead, which allows us to manually provide the
is_negative flag.
This commit is contained in:
Matthew Olsson 2021-04-15 13:28:02 -07:00 committed by Linus Groh
parent bf8223926a
commit d719e745fb
2 changed files with 11 additions and 4 deletions

View file

@ -390,7 +390,11 @@ void FormatBuilder::put_f64(
StringBuilder string_builder;
FormatBuilder format_builder { string_builder };
format_builder.put_i64(static_cast<i64>(value), base, false, upper_case, false, Align::Right, 0, ' ', sign_mode);
bool is_negative = value < 0.0;
if (is_negative)
value = -value;
format_builder.put_u64(static_cast<u64>(value), base, false, upper_case, false, Align::Right, 0, ' ', sign_mode, is_negative);
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
@ -398,9 +402,6 @@ void FormatBuilder::put_f64(
// https://youtu.be/4P_kbF0EbZM (Stephan T. Lavavej “Floating-Point <charconv>: Making Your Code 10x Faster With C++17's Final Boss”)
value -= static_cast<i64>(value);
if (value < 0)
value = -value;
double epsilon = 0.5;
for (size_t i = 0; i < precision; ++i)
epsilon /= 10.0;

View file

@ -273,6 +273,12 @@ TEST_CASE(yay_this_implementation_sucks)
EXPECT_EQ(String::formatted("{:.0}", .99999999999), "0");
}
TEST_CASE(magnitude_less_than_zero)
{
EXPECT_EQ(String::formatted("{}", -0.654), "-0.654");
EXPECT_EQ(String::formatted("{}", 0.654), "0.654");
}
TEST_CASE(format_nullptr)
{
EXPECT_EQ(String::formatted("{}", nullptr), String::formatted("{:p}", static_cast<FlatPtr>(0)));