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
Recommend user to use "G17" for round-trip converting for double numbers. #2919
Comments
I'm not opposing your suggestion, in fact, I highly welcome adding this detail, knowing that I have, on different occasions, fallen for the trap of using only "R". However, I would like to suggest adding a note, or even a code example, that shows how to get the minimal exact representation. That is, try 15 digits precision, test roundtrip, if fail, try 16 digits precision, if fail, try 17 digits precision (always succeeds). It may also be worth mentioning that there is no built-in way to get a minimal roundtrippable representation in scientific notation (both "R" and "G" only switch to scientific if they have to). The above solution can be used to find a similar value with the "E" format specifier. As an example, the number in your post, It may be worthwhile to include such numbers as examples. |
Do we have a real world scenario that needs to find the exactly minimal round-trippable precision for a specific number?
Yes. It would be good to describe the reason why G17 specifier can guarantee the roundtrip. cc @rpetrusha who is working on this issue. |
@mazong1123, I can think of at least two. My own real-world scenario, writing compilers. Some language specifications require this (in my case XSLT/XPath). The other one being that it is often required to show a number in the shortest form possible. This is also reflected by the need for specifiers like "G" in the first place (which returns a scientific notation or decimal notation, whichever is shorter). A third one is, obviously, educational: showing users how this works or can work also shows users how they can implement this for other precisions. Personally, I have never understood why there is no format specifier that can do this, or why "R" skips from 15 to 17, not testing 16 digits precision. After all, the sum of all numbers requiring 17 digits is exponentially smaller than the sum of all numbers requiring 16 digits. We should not strive to default to the exceptional case, but strive to default to the common case. Finally, this argument is the same for whether you would return "1.220" or "1.22": the "R" specifier already returns the shortest form in all scenarios, except for 15-17 digits numbers. So adding such an example is basically filling the gap left by a less-than-optimally working "R" format specifier. Anybody who does not care about "shortest form", but only about roundtrippability, does not need "R" to begin with, they can just use "E50" or something (though obviously, "E16", returning 17 digits precision, is enough). |
I've opened PR #3101 to change the recommended format string for round-tripping from "R" to "G17". Determining the minimal exact representation is outside the scope of the Standard Numeric Format Strings topic, @abelbraaksma. If you feel strongly that you'd like one to be published, please open a separate issue. And if you'd be interested in writing it yourself, contributions are certainly welcome. |
Today we're suggesting user to use "R" for round-trip converting for double numbers.
https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings (See
The Round-trip ("R") Format Specifier
)https://msdn.microsoft.com/en-us/library/kfsatb94(v=vs.110).aspx
However,
double.ToString("R")
will introduce a bug caused by its design: https://stackoverflow.com/questions/24299692/why-is-a-round-trip-conversion-via-a-string-not-safe-for-a-doubleGenerally speaking, "R" specifier tries to convert double to string in 15 digits precision first. If the precision is not enough for round tripping, it goes to convert in 17 digits precision. However, for some numbers (e.g.
0.84551240822557006
) it would wrongly pick 15 digits precision (we should pick 17 digits), which cannot guarantee round-trip.The documents listed above have warnings for users and suggest users to use "G17" if the code compiled using
/platform:x64
or/platform:anycpu
. This is less useful for real-world users. Because users are almost going to use "R" at first time. Later when they find a bug on production they would be frustrated.After discussed in dotnet/coreclr#13140 , considering the comparability, we decide to not change the current behavior of "R" specifier, but we need to update the document to RECOMMEND user to use "G17" for round-tripping instead of using "R".
The text was updated successfully, but these errors were encountered: