Skip to content
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

Floating-point formatting defaults differ from iostream/Boost.Format #1893

Closed
dalle opened this issue Sep 22, 2020 · 6 comments
Closed

Floating-point formatting defaults differ from iostream/Boost.Format #1893

dalle opened this issue Sep 22, 2020 · 6 comments

Comments

@dalle
Copy link
Contributor

dalle commented Sep 22, 2020

The default is "g" in std::iostreams and boost::format. This is also the default in .NET-based languages (C#, F#, VB.NET), Rust, R.
The default is "g with at least one digit past the decimal point" in fmt. This is also the default in Python.

This can lead to hard to find bugs when porting from one of these libraries to fmt.

The rationale for the default in fmt is that;

The default gives you round trip guarantees while g does not.
Originally posted by @vitaut in #1889 (comment)

May I ask how is "1.0" more round-trippable than "1", given a floating-point context for the value of 1?
The documentation does not mention round-trip guarantees for the {} format specifier, perhaps it should?
May I suggest another format specifier for round-tripping, what about {:R}?

But as per usual, there are almost uncountable different ways software engineers prefer their floating-points to be formatted by default. 😂

@vitaut
Copy link
Contributor

vitaut commented Sep 22, 2020

May I ask how is "1.0" more round-trippable than "1", given a floating-point context for the value of 1?

This is not what I was saying. I was explaining what is the main difference between the default format and g.

At this point the format is fixed for compatibility with std::format (and Python). If you want compatibility with printf's %g, please use the g format specifier.

@vitaut vitaut closed this as completed Sep 22, 2020
@dalle
Copy link
Contributor Author

dalle commented Sep 22, 2020

In lack of having access to the C++20 standard, I read https://en.cppreference.com/w/cpp/utility/format/formatter which currently state the following available floating-point presentation types;

none: If precision is specified, produces the output as if by calling std::to_chars(first, last, value, std::chars_format::general, precision) where precision is the specified precision; otherwise, the output is produced as if by calling std::to_chars(first, last, value).

That lead me to test what std::to_chars(first, last, 1.0) would produce, and it produce "1" on my system. That may be an error though, and cppreference isn't always 100% standardese either.

@vitaut
Copy link
Contributor

vitaut commented Sep 23, 2020

What do the specs say about to_chars?

@vitaut
Copy link
Contributor

vitaut commented Sep 23, 2020

to_chars specs are somewhat vague but it looks like the intent is to not emit the trailing zero, so I changed the default accordingly in 2d4fde3 to make it consistent with std::to_chars (and therefore std::format). It is possible to get trailing zero and decimal point with #. Thanks for reporting.

@cgmb
Copy link

cgmb commented Jun 8, 2021

Did the docs get updated? They state that the default presentation type for floating point values is:

Similar to 'g', except that fixed-point notation, when used, has at least one digit past the decimal point. The default precision is as high as needed to represent the particular value.

I might just be misunderstanding that, but it seems to describe the old behaviour.

@vitaut
Copy link
Contributor

vitaut commented Jun 8, 2021

They are updated now (https://fmt.dev/dev/syntax.html), thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants