-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default floating-point formatting does not produce shortest outputs; mismatch with std::format
#3649
Comments
|
I honestly feel like the shortest string is what people may expect, but that's of course just a subjective opinion. If you are going to change the behavior (or accept a PR that does so) in the future, it would be great. If not, please feel free to close this, but I think this difference needs to be documented anyway in places like https://fmt.dev/dev/api.html#compatibility-with-c-20-std-format. |
I am open to PRs to address this backed by more analysis of the effects of the change and concrete examples. |
Note that this also results in the rather surprising (to me) behavior that eg 123456792.0f formats as "123456790", the last digit apparently being wrong. But these roundtrip to the same float and 123456790 is shorter in the sense of having fewer sigfigs.
|
This is unrelated and I am surprised that |
Why is that "garbage" in this case? That value is perfectly representable as a Is there a way to control the number of digits that rounds in this particular case, and without exponential notation, or should this be filed as another issue altogether? |
That's the term they used in the Steele and White paper. You can control precision, so there is no issue here. |
So this seems to be because So... this is interesting... we may need to look at what EDIT: https://github.com/microsoft/STL/blob/192a84008a59ac4d2e55681e1ffac73535788674/stl/inc/xcharconv_ryu.h#L1368 |
Did some investigation what other languages do: Python:
Java: System.out.println(1234000.0);
System.out.println(12340000.0);
Rust (using debug since the default format appears to be fixed): println!("{:?}", 1234000000000000.0);
println!("{:?}", 12340000000000000.0);
JavaScript:
Swift: print(1234000000000000.0)
print(12340000000000000.0)
Python and Rust have the same threshold as {fmt} which is not surprising since the latter two formatting facilities are based on Python's. Swift has the same threshold too. Java has threshold of 7: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#toString-double-. JavaScript has even larger threshold of 21 because why not. |
Another observation is that having a threshold of 16 is slightly weird for FP representations other than IEEE754 binary64. |
The choice of shortest output size doesn't seem to be motivated in P0067, contradict other choices of representation (redundant exponent digits and sign) and was definitely not intentional in |
Clarified the difference in 373855c and will consider writing a paper to fix this in |
Nice, it would be nice if this fix also lands in |
As far as I understand, the default formatting option should produce the shortest output, not just in the number of significand digits, but also in the number of actual characters. At least that seems to be how
std::format
is specified, according to thestd::to_chars
specifications.However, it seems currently
fmt
picks the fixed-point format whenever the exponent is between-4
and16
, regardless of the number of characters it will produce:fmt/include/fmt/format.h
Line 2644 in 3baaa8d
Is this an intended divergence? Or maybe I misunderstood how
std::format
is specified?For what it's worth, it seems MS STL implementation of
std::format
does what I described.The text was updated successfully, but these errors were encountered: