I'm talking about automatic switching between exponential and non-exponential form based on magnitude; printing numbers fit for human consumption. The default format is so silly that you're basically required to use exponential format in any sort of general context; but then I end up with those occassional late nights where I see 5e0 and it takes me a couple of seconds to remember whether this is larger than or less than 1.
That's just silly!
...and yes, I know what you're about to say, and I've already tried exactly that. A wrapper type doesn't cut it. You can't wrap every element of every Vec and MyOneOffStruct that you ever need to debug.
g, G The double argument is converted in style f or e (or F or E
for G conversions). The precision specifies the number of
significant digits. If the precision is missing, 6 digits are
given; if the precision is zero, it is treated as 1. Style e
is used if the exponent from its conversion is less than -4 or
greater than or equal to the precision. Trailing zeros are
removed from the fractional part of the result; a decimal
point appears only if it is followed by at least one digit.
It's close (and my original title was "General floating number point formatting", after what I assume "g" stands for), though my preference is to default to minimal round-trip precision like our existing representations do (as well as the defaults in Haskell and Python).
I have never had a case where "{}" or "{:e}" for a float was the formatting I wanted. I have always had to work around it.
In serde_json I have been using dtoa to get reasonable printing of floats. The API is somewhat less convenient but it is faster for serde_json's use case than std::fmt, and it seems to use the same formatting as Python in your examples. [playground]
Lacking a %g equivalent is frustrating. There doesn't even seem to be a good crate for this (@dtolnay's does not appear to support displaying a particular number of significant digits). I pretty much only ever want to print a float with a specific number of significant digits, and rust does not seem to make this possible short of calling out to libc.
The %g format specifier for printf is different from what current Python does. Python produces a short string which converts back to the original value. %g is lossy. But then, C does not require that string-to-floating-point is exact, either, so C isn't really a good model here (Java is much better in this regard, as far as languages with a separate specification go).