vppinfra: fix float rounding in format function 95/42095/1
authorPierre Pfister <ppfister@cisco.com>
Thu, 19 Dec 2024 15:49:21 +0000 (16:49 +0100)
committerPierre Pfister <ppfister@cisco.com>
Tue, 7 Jan 2025 08:47:55 +0000 (09:47 +0100)
The current VPP formating for floats tries to round number to the
closest value (depending on the number of requested digits), but fails
to do so when the last printed digit is 9 (because carries are hard...).

This commits fixes this by adding 0.5 * 10^n_fraction_digits
to the value and then ignoring digits past the printed ones.

Note that when the number is exactly midway, like 9.5, the value is
rounded up, as this seems to be the clib behavior as well.

Type: fix
Change-Id: I03ce04ea6a24b84eeffd548d3f7bd306c58ce36d
Signed-off-by: Pierre Pfister <ppfister@cisco.com>
src/vppinfra/format.c

index 642d3e2..5cdc3b2 100644 (file)
@@ -733,6 +733,12 @@ format_float (u8 * s, f64 x, uword n_fraction_digits, uword output_style)
       sign = 1;
     }
 
+  /* Round x to closest value with n_fraction_digits digits after '.' */
+  f64 rounding = 0.5;
+  for (uword i = 0; i < n_fraction_digits; i++)
+    rounding *= 0.1;
+  x += rounding;
+
   /* Check for not-a-number. */
   if (isnan (x))
     return format (s, "%cNaN", sign ? '-' : '+');
@@ -789,11 +795,6 @@ format_float (u8 * s, f64 x, uword n_fraction_digits, uword output_style)
          x -= 1;
        }
 
-      /* Round last printed digit. */
-      if (decimal_point <= 0
-         && n_fraction_done + 1 == n_fraction_digits && digit < 9)
-       digit += x >= .5;
-
       vec_add1 (s, '0' + digit);
 
       /* Move rightwards towards/away from decimal point. */