Fixing the double/float formatting code to use a fallback precision for custom-format...
authorTanner Gooding <tagoo@outlook.com>
Wed, 13 Feb 2019 15:36:57 +0000 (07:36 -0800)
committerGitHub <noreply@github.com>
Wed, 13 Feb 2019 15:36:57 +0000 (07:36 -0800)
src/System.Private.CoreLib/shared/System/Number.Formatting.cs

index b4f6e92..cd61336 100644 (file)
@@ -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;