From 556e22de1291b6b1a33a5f1080b2bf3125b140e7 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 13 Feb 2019 07:36:57 -0800 Subject: [PATCH] Fixing the double/float formatting code to use a fallback precision for custom-format strings. (#22522) --- .../shared/System/Number.Formatting.cs | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs index b4f6e92..cd61336 100644 --- a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs +++ b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs @@ -250,6 +250,15 @@ namespace System 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). + // In order to support more digits, we would need to update ParseFormatSpecifier to pre-parse + // the format and determine exactly how many digits are being requested and whether they + // represent "significant digits" or "digits after the decimal point". + private const int SinglePrecisionCustomFormat = 6; + private const int DoublePrecisionCustomFormat = 15; + private const int DefaultPrecisionExponentialFormat = 6; private const int ScaleNAN = unchecked((int)0x80000000); @@ -525,6 +534,13 @@ namespace System char fmt = ParseFormatSpecifier(format, out int precision); byte* pDigits = stackalloc byte[DoubleNumberBufferLength]; + if (fmt == '\0') + { + // For back-compat we currently specially treat the precision for custom + // format specifiers. The constant has more details as to why. + precision = DoublePrecisionCustomFormat; + } + NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, pDigits, DoubleNumberBufferLength); number.IsNegative = double.IsNegative(value); @@ -563,6 +579,7 @@ namespace System } else { + Debug.Assert(precision == DoublePrecisionCustomFormat); NumberToStringFormat(ref sb, ref number, format, info); } return null; @@ -605,6 +622,13 @@ namespace System char fmt = ParseFormatSpecifier(format, out int precision); byte* pDigits = stackalloc byte[SingleNumberBufferLength]; + if (fmt == '\0') + { + // For back-compat we currently specially treat the precision for custom + // format specifiers. The constant has more details as to why. + precision = SinglePrecisionCustomFormat; + } + NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, pDigits, SingleNumberBufferLength); number.IsNegative = float.IsNegative(value); @@ -643,6 +667,7 @@ namespace System } else { + Debug.Assert(precision == SinglePrecisionCustomFormat); NumberToStringFormat(ref sb, ref number, format, info); } return null; -- 2.7.4