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

Fixing the double/float formatting code to use a fallback precision for custom-format strings. #22522

Merged
merged 1 commit into from Feb 13, 2019

Conversation

@tannergooding
Copy link
Member

commented Feb 11, 2019

This ensures that custom-format strings that are requesting between 1-15 digits continue printing the same as before (as was the case with the standard-format strings). For custom-format strings in particular, and unlike standard-format strings, they will also continue printing the same number of digits as before when the custom-format string is requesting above 15 digits. I do think it would be desirable to "pre-parse" the custom-format string and determine exactly how many digits the user is requesting (and I believe we could do so in a way that does not cause a perf-regression and that may actually provide some perf-gains for common cases), but that is a more-involved change.

@tannergooding

This comment has been minimized.

Copy link
Member Author

commented Feb 11, 2019

@@ -250,6 +250,15 @@ internal static partial class Number
private const int SinglePrecision = 9;
private const int DoublePrecision = 17;

// SinglePrecisionCustomFormat and DoublePrecisionCustomFormat are used to ensure that
// custom format strings return the same string as in previous releases when the format
// would return x digits or less (where x is the value of the corresponding constant).

This comment has been minimized.

Copy link
@tannergooding

tannergooding Feb 11, 2019

Author Member

This part in particular (returning the same string as before when less than x digits are requested) is also true for standard-numeric format strings. For the standard-formats, we only differ when more than 15 digits are requested and for the default case on G and R.

@jkotas

This comment has been minimized.

Copy link
Member

commented Feb 11, 2019

Is there going to be a matching corefx test update/addition?

@jkotas

This comment has been minimized.

Copy link
Member

commented Feb 11, 2019

I would be ok with me to wait until somebody reports it as a real problem; but if you would like to do it now - that is fine with me as well.

@tannergooding

This comment has been minimized.

Copy link
Member Author

commented Feb 11, 2019

Is there going to be a matching corefx test update/addition?

Yes. I plan on adding some tests to cover this code-path.

@tannergooding

This comment has been minimized.

Copy link
Member Author

commented Feb 11, 2019

I would be ok with me to wait until somebody reports it as a real problem; but if you would like to do it now - that is fine with me as well.

For this particular case, I feel it is better to cover it now. Not specifying an explicit precision means that the digit generator will produce the shortest roundtrippable string, rather than the first 'X' significant digits. This results in cases where the number differs and it is not clearly better. As an extreme example, you have values like double.Epsilon where the digit generator will produce 5 rather than 494065645841247. Then, when formatting if the user has requested 2 significant digits, they will get just 5E-324 rather than 4.9E-324.

For people who are relying on custom-format strings (who are likely users expecting a particular format) to return the requested number of digits, this is a significant breaking change (especially for common cases like "0.00" or "0.0E0"). I have, in general, tried to ensure that users explicitly requesting a given number of digits are getting exactly what they requested (and for requests less than 15 digits, we can make this completely non-breaking).

@tannergooding

This comment has been minimized.

Copy link
Member Author

commented Feb 12, 2019

Also CC. @eerhardt who was reviewed many of the previous changes here.

@@ -525,6 +534,13 @@ private static unsafe string FormatDouble(ref ValueStringBuilder sb, double valu
char fmt = ParseFormatSpecifier(format, out int precision);
byte* pDigits = stackalloc byte[DoubleNumberBufferLength];

if (fmt == '\0')

This comment has been minimized.

Copy link
@eerhardt

eerhardt Feb 12, 2019

Member

(super nit): I think we should be consistent with how we are checking the fmt variable in this method.

Here we are using fmt == '\0'. Below: fmt != 0.

This comment has been minimized.

Copy link
@tannergooding

tannergooding Feb 12, 2019

Author Member

I can update the below one in a separate PR.

I think explicitly checking '\0' makes it much clearer that we are checking for the terminating null.

@tannergooding

This comment has been minimized.

Copy link
Member Author

commented Feb 12, 2019

Any other feedback here, or is this good to merge?

@tannergooding tannergooding merged commit 556e22d into dotnet:master Feb 13, 2019

67 checks passed

CentOS7.1 x64 Checked Innerloop Build and Test Build finished.
Details
CentOS7.1 x64 Debug Innerloop Build Build finished.
Details
Linux-musl x64 Debug Build Build finished.
Details
OSX10.12 x64 Checked Innerloop Build and Test Build finished.
Details
Ubuntu arm Cross Checked Innerloop Build and Test Build finished.
Details
Ubuntu arm Cross Checked crossgen_comparison Build and Test Build finished.
Details
Ubuntu arm Cross Checked no_tiered_compilation_innerloop Build and Test Build finished.
Details
Ubuntu arm Cross Release crossgen_comparison Build and Test Build finished.
Details
Ubuntu x64 Checked CoreFX Tests Build finished.
Details
Ubuntu x64 Checked Innerloop Build and Test Build finished.
Details
Ubuntu x64 Checked Innerloop Build and Test (Jit - TieredCompilation=0) Build finished.
Details
Ubuntu x64 Formatting Build finished.
Details
WIP Ready for review
Details
Windows_NT x64 Checked CoreFX Tests Build finished.
Details
Windows_NT x64 Checked Innerloop Build and Test Build finished.
Details
Windows_NT x64 Checked Innerloop Build and Test (Jit - TieredCompilation=0) Build finished.
Details
Windows_NT x64 Formatting Build finished.
Details
Windows_NT x64 Release CoreFX Tests Build finished.
Details
Windows_NT x64 full_opt ryujit CoreCLR Perf Tests Correctness Build finished.
Details
Windows_NT x64 min_opt ryujit CoreCLR Perf Tests Correctness Build finished.
Details
Windows_NT x86 Checked Innerloop Build and Test Build finished.
Details
Windows_NT x86 Checked Innerloop Build and Test (Jit - TieredCompilation=0) Build finished.
Details
Windows_NT x86 Release Innerloop Build and Test Build finished.
Details
Windows_NT x86 full_opt ryujit CoreCLR Perf Tests Correctness Build finished.
Details
Windows_NT x86 min_opt ryujit CoreCLR Perf Tests Correctness Build finished.
Details
coreclr-ci Build #20190211.714 succeeded
Details
coreclr-ci (Build Linux arm checked) Build Linux arm checked succeeded
Details
coreclr-ci (Build Linux arm debug) Build Linux arm debug succeeded
Details
coreclr-ci (Build Linux arm release) Build Linux arm release succeeded
Details
coreclr-ci (Build Linux arm64 checked) Build Linux arm64 checked succeeded
Details
coreclr-ci (Build Linux arm64 debug) Build Linux arm64 debug succeeded
Details
coreclr-ci (Build Linux arm64 release) Build Linux arm64 release succeeded
Details
coreclr-ci (Build Linux_musl x64 checked) Build Linux_musl x64 checked succeeded
Details
coreclr-ci (Build Linux_musl x64 debug) Build Linux_musl x64 debug succeeded
Details
coreclr-ci (Build Linux_musl x64 release) Build Linux_musl x64 release succeeded
Details
coreclr-ci (Build Linux_rhel6 x64 checked) Build Linux_rhel6 x64 checked succeeded
Details
coreclr-ci (Build Linux_rhel6 x64 debug) Build Linux_rhel6 x64 debug succeeded
Details
coreclr-ci (Build Linux_rhel6 x64 release) Build Linux_rhel6 x64 release succeeded
Details
coreclr-ci (Build Windows_NT arm Checked) Build Windows_NT arm Checked succeeded
Details
coreclr-ci (Build Windows_NT arm Debug) Build Windows_NT arm Debug succeeded
Details
coreclr-ci (Build Windows_NT arm64 Checked) Build Windows_NT arm64 Checked succeeded
Details
coreclr-ci (Build Windows_NT arm64 Debug) Build Windows_NT arm64 Debug succeeded
Details
coreclr-ci (Build Windows_NT x64 Checked) Build Windows_NT x64 Checked succeeded
Details
coreclr-ci (Build Windows_NT x64 Debug) Build Windows_NT x64 Debug succeeded
Details
coreclr-ci (Build Windows_NT x86 Checked) Build Windows_NT x86 Checked succeeded
Details
coreclr-ci (Build Windows_NT x86 Debug) Build Windows_NT x86 Debug succeeded
Details
coreclr-ci (Test Pri0 Linux x64 checked) Test Pri0 Linux x64 checked succeeded
Details
coreclr-ci (Test Pri0 OSX x64 checked) Test Pri0 OSX x64 checked succeeded
Details
coreclr-ci (Test Pri0 Windows_NT arm checked) Test Pri0 Windows_NT arm checked succeeded
Details
coreclr-ci (Test Pri0 Windows_NT arm64 checked) Test Pri0 Windows_NT arm64 checked succeeded
Details
coreclr-ci (Test Pri0 Windows_NT x64 checked) Test Pri0 Windows_NT x64 checked succeeded
Details
coreclr-ci (Test Pri0 Windows_NT x86 checked) Test Pri0 Windows_NT x86 checked succeeded
Details
coreclr-ci (Test pri0 Linux arm checked) Test pri0 Linux arm checked succeeded
Details
coreclr-ci (Test pri0 Linux arm64 checked) Test pri0 Linux arm64 checked succeeded
Details
coreclr-ci (Test pri0 Linux_musl x64 checked) Test pri0 Linux_musl x64 checked succeeded
Details
coreclr-ci (Test pri0 Linux_rhel6 x64 checked) Test pri0 Linux_rhel6 x64 checked succeeded
Details
coreclr-ci (build Linux x64 Checked) build Linux x64 Checked succeeded
Details
coreclr-ci (build Linux x64 Debug) build Linux x64 Debug succeeded
Details
coreclr-ci (build Linux x64 Release) build Linux x64 Release succeeded
Details
coreclr-ci (build OSX x64 Checked) build OSX x64 Checked succeeded
Details
coreclr-ci (build OSX x64 Debug) build OSX x64 Debug succeeded
Details
coreclr-ci (build OSX x64 Release) build OSX x64 Release succeeded
Details
coreclr-ci (build Windows_NT arm Release) build Windows_NT arm Release succeeded
Details
coreclr-ci (build Windows_NT arm64 Release) build Windows_NT arm64 Release succeeded
Details
coreclr-ci (build Windows_NT x64 Release) build Windows_NT x64 Release succeeded
Details
coreclr-ci (build Windows_NT x86 Release) build Windows_NT x86 Release succeeded
Details
license/cla All CLA requirements met.
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.