How to dynamically format a float with leading zeroes

I am trying to format a float with the pattern DD.dddd. The precision of the decimal place may optionally be supplied by users (e.g., someone may format my type with {:.3}, and I should output 3 decimal places in that case.

I am struggling to write this behavior. The closest I can get is both inelegant, and does not handle {.0} correctly. I've read the format string docs, and I don't think I'm missing a cleaner way.

Here is a playground link which includes my best attempt, and a series of tests of the behavior I would like.

A quick explainer of my current approach, as it's a little hairy:

// p is precision
// n is the float
write!(f, "{2:0>0$.1$}", p+3, p, n)

From left to right, this will:

  • 2: format the 2nd argument (0-indexed)
  • 0>: left-align the result, using 0 as the fill character
  • 0: dynamically read the total width of the output from the 0`th argument.
  • .1: specify precision of the float from the 1`st argument.

Frustratingly, this does not correctly handle outputs which do not include a decimal point.

        match f.precision() {
            Some(0) => write!(f, "{n:02.0}"),
            Some(p) => write!(f, "{n:0>0$.1$}", p+3, p),
            None => write!(f, "{n:07.4}"),
        }

(I just fiddled around until your tests passed.)

3 Likes

that’s perfect, thank you very much

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.