Jelajahi Sumber

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.
Matthew Olsson 4 tahun lalu
induk
melakukan
d719e745fb
2 mengubah file dengan 11 tambahan dan 4 penghapusan
  1. 5 4
      AK/Format.cpp
  2. 6 0
      AK/Tests/TestFormat.cpp

+ 5 - 4
AK/Format.cpp

@@ -390,7 +390,11 @@ void FormatBuilder::put_f64(
     StringBuilder string_builder;
     StringBuilder string_builder;
     FormatBuilder format_builder { 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) {
     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
         // 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”)
         // 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);
         value -= static_cast<i64>(value);
 
 
-        if (value < 0)
-            value = -value;
-
         double epsilon = 0.5;
         double epsilon = 0.5;
         for (size_t i = 0; i < precision; ++i)
         for (size_t i = 0; i < precision; ++i)
             epsilon /= 10.0;
             epsilon /= 10.0;

+ 6 - 0
AK/Tests/TestFormat.cpp

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