diff --git a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Tag.cs b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Tag.cs index 88cb2f0ee95c2f..b9cc53ceb237b1 100644 --- a/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Tag.cs +++ b/src/libraries/System.Formats.Cbor/tests/Writer/CborWriterTests.Tag.cs @@ -158,7 +158,7 @@ public static void WriteInteger_SingleValue_HappyPath(string valueString, string [InlineData("1", "c4820001")] [InlineData("-1", "c4820020")] [InlineData("1.1", "c482200b")] - [InlineData("1.000", "c4820001")] + [InlineData("1.000", "c482221903e8")] [InlineData("273.15", "c48221196ab3")] [InlineData("79228162514264337593543950335", "c48200c24cffffffffffffffffffffffff")] // decimal.MaxValue [InlineData("7922816251426433759354395033.5", "c48220c24cffffffffffffffffffffffff")] diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs index a07153cad25eca..382eb1ccf82a55 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs @@ -358,9 +358,10 @@ private static unsafe bool TryParseNumber(ref char* str, char* strEnd, NumberSty { number.Scale++; } - else if (digCount < maxDigCount) + + if (digCount < maxDigCount) { - // Handle a case like "53.0". We need to ignore trailing zeros in the fractional part, so we keep a count of the number of trailing zeros and update digCount later + // Handle a case like "53.0". We need to ignore trailing zeros in the fractional part for floating point numbers, so we keep a count of the number of trailing zeros and update digCount later if (ch == '0') { numberOfTrailingZeros++; @@ -395,17 +396,8 @@ private static unsafe bool TryParseNumber(ref char* str, char* strEnd, NumberSty } bool negExp = false; - if (digEnd == maxDigCount && numberOfTrailingZeros > 0 && number.HasNonZeroTail) - { - // We have a non-zero digit in the input past maxDigitCount. We already handle this properly. - number.DigitsCount = digEnd; - } - else - { - // We have trailing 0s in the fractional part. We can strip it all out - number.DigitsCount = digEnd - numberOfTrailingZeros; - } - number.Digits[number.DigitsCount] = (byte)('\0'); + number.DigitsCount = digEnd; + number.Digits[digEnd] = (byte)('\0'); if ((state & StateDigits) != 0) { if ((ch == 'E' || ch == 'e') && ((styles & NumberStyles.AllowExponent) != 0)) @@ -449,6 +441,20 @@ private static unsafe bool TryParseNumber(ref char* str, char* strEnd, NumberSty ch = p < strEnd ? *p : '\0'; } } + + if (number.Kind == NumberBufferKind.FloatingPoint && !number.HasNonZeroTail) + { + // Adjust the number buffer for trailing zeros + int numberOfFractionalDigits = digEnd - number.Scale; + if (numberOfFractionalDigits > 0) + { + numberOfTrailingZeros = Math.Min(numberOfTrailingZeros, numberOfFractionalDigits); + Debug.Assert(numberOfTrailingZeros >= 0); + number.DigitsCount = digEnd - numberOfTrailingZeros; + number.Digits[number.DigitsCount] = (byte)('\0'); + } + } + while (true) { if (!IsWhite(ch) || (styles & NumberStyles.AllowTrailingWhite) == 0) @@ -2025,7 +2031,7 @@ private static bool TrailingZeros(ReadOnlySpan value, int index) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe char* MatchNegativeSignChars(char* p, char* pEnd, NumberFormatInfo info) { - char *ret = MatchChars(p, pEnd, info.NegativeSign); + char* ret = MatchChars(p, pEnd, info.NegativeSign); if (ret == null && info.AllowHyphenDuringParsing && p < pEnd && *p == '-') { ret = p + 1; diff --git a/src/libraries/System.Runtime/tests/System/DecimalTests.cs b/src/libraries/System.Runtime/tests/System/DecimalTests.cs index e4f3c9d8012924..35069a81e61611 100644 --- a/src/libraries/System.Runtime/tests/System/DecimalTests.cs +++ b/src/libraries/System.Runtime/tests/System/DecimalTests.cs @@ -1500,6 +1500,14 @@ public static void ToString_InvalidFormat_ThrowsFormatException() Assert.Throws(() => f.ToString("E" + intMaxPlus1String)); } + [Theory] + [InlineData("3.00")] + public void TestRoundTripDecimalToString(string input) + { + decimal d = Decimal.Parse(input, NumberStyles.Number, NumberFormatInfo.InvariantInfo); + string dString = d.ToString(CultureInfo.InvariantCulture); + Assert.Equal(input, dString); + } public static IEnumerable Truncate_TestData() { yield return new object[] { 123m, 123m }; diff --git a/src/libraries/System.Runtime/tests/System/DoubleTests.cs b/src/libraries/System.Runtime/tests/System/DoubleTests.cs index 8403fe131d64cd..d0bfcfb41419ca 100644 --- a/src/libraries/System.Runtime/tests/System/DoubleTests.cs +++ b/src/libraries/System.Runtime/tests/System/DoubleTests.cs @@ -290,6 +290,13 @@ public static IEnumerable Parse_Valid_TestData() yield return new object[] { "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", defaultStyle, invariantFormat, 0.0 }; yield return new object[] { "0.005", defaultStyle, invariantFormat, 0.005 }; yield return new object[] { "0.0500", defaultStyle, invariantFormat, 0.05 }; + yield return new object[] { "6250000000000000000000000000000000e-12", defaultStyle, invariantFormat, 6.25e21 }; + yield return new object[] { "6250000e0", defaultStyle, invariantFormat, 6.25e6 }; + yield return new object[] { "6250100e-5", defaultStyle, invariantFormat, 62.501 }; + yield return new object[] { "625010.00e-4", defaultStyle, invariantFormat, 62.501 }; + yield return new object[] { "62500e-4", defaultStyle, invariantFormat, 6.25 }; + yield return new object[] { "62500", defaultStyle, invariantFormat, 62500.0 }; + yield return new object[] { "10e-3", defaultStyle, invariantFormat, 0.01 }; yield return new object[] { (123.1).ToString(), NumberStyles.AllowDecimalPoint, null, 123.1 }; yield return new object[] { (1000.0).ToString("N0"), NumberStyles.AllowThousands, null, 1000.0 }; diff --git a/src/libraries/System.Runtime/tests/System/HalfTests.cs b/src/libraries/System.Runtime/tests/System/HalfTests.cs index e851f28815fbec..926034b5b70919 100644 --- a/src/libraries/System.Runtime/tests/System/HalfTests.cs +++ b/src/libraries/System.Runtime/tests/System/HalfTests.cs @@ -685,6 +685,11 @@ public static IEnumerable Parse_Valid_TestData() yield return new object[] { "0.000000000000000000", defaultStyle, invariantFormat, 0.0f }; yield return new object[] { "0.005", defaultStyle, invariantFormat, 0.005f }; yield return new object[] { "0.0400", defaultStyle, invariantFormat, 0.04f }; + yield return new object[] { "1200e0", defaultStyle, invariantFormat, 1200.0f }; + yield return new object[] { "120100e-4", defaultStyle, invariantFormat, 12.01f }; + yield return new object[] { "12010.00e-4", defaultStyle, invariantFormat, 1.201f }; + yield return new object[] { "12000e-4", defaultStyle, invariantFormat, 1.2f }; + yield return new object[] { "1200", defaultStyle, invariantFormat, 1200.0f }; yield return new object[] { (123.1f).ToString(), NumberStyles.AllowDecimalPoint, null, 123.1f }; yield return new object[] { (1000.0f).ToString("N0"), NumberStyles.AllowThousands, null, 1000.0f }; diff --git a/src/libraries/System.Runtime/tests/System/Int32Tests.cs b/src/libraries/System.Runtime/tests/System/Int32Tests.cs index f64df4bcc31035..fca800ca2921ff 100644 --- a/src/libraries/System.Runtime/tests/System/Int32Tests.cs +++ b/src/libraries/System.Runtime/tests/System/Int32Tests.cs @@ -355,6 +355,12 @@ public static IEnumerable Parse_Valid_TestData() yield return new object[] { "123123", NumberStyles.AllowLeadingSign, new NumberFormatInfo() { NegativeSign = "123" }, -123 }; yield return new object[] { "123123", NumberStyles.AllowLeadingSign, new NumberFormatInfo() { PositiveSign = "12312" }, 3 }; yield return new object[] { "123123", NumberStyles.AllowLeadingSign, new NumberFormatInfo() { NegativeSign = "12312" }, -3 }; + + // Test trailing zeros + yield return new object[] { "3.00", NumberStyles.Number, CultureInfo.InvariantCulture, 3 }; + yield return new object[] { "3.00000000", NumberStyles.Number, CultureInfo.InvariantCulture, 3 }; + yield return new object[] { "3.000000000", NumberStyles.Number, CultureInfo.InvariantCulture, 3 }; + yield return new object[] { "3.0000000000", NumberStyles.Number, CultureInfo.InvariantCulture, 3 }; } [Theory] diff --git a/src/libraries/System.Runtime/tests/System/SingleTests.cs b/src/libraries/System.Runtime/tests/System/SingleTests.cs index 1fa4916c172e80..962621d05c15bf 100644 --- a/src/libraries/System.Runtime/tests/System/SingleTests.cs +++ b/src/libraries/System.Runtime/tests/System/SingleTests.cs @@ -295,6 +295,12 @@ public static IEnumerable Parse_Valid_TestData() yield return new object[] { "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", defaultStyle, invariantFormat, 0.0f }; yield return new object[] { "0.005", defaultStyle, invariantFormat, 0.005f }; yield return new object[] { "0.0500", defaultStyle, invariantFormat, 0.05f }; + yield return new object[] { "6250000000000000000000000000000000e-12", defaultStyle, invariantFormat, 6.25e21f }; + yield return new object[] { "6250000e0", defaultStyle, invariantFormat, 6.25e6f }; + yield return new object[] { "6250100e-5", defaultStyle, invariantFormat, 62.501f }; + yield return new object[] { "625010.00e-4", defaultStyle, invariantFormat, 62.501f }; + yield return new object[] { "62500e-4", defaultStyle, invariantFormat, 6.25f }; + yield return new object[] { "62500", defaultStyle, invariantFormat, 62500.0f }; yield return new object[] { (123.1f).ToString(), NumberStyles.AllowDecimalPoint, null, 123.1f }; yield return new object[] { (1000.0f).ToString("N0"), NumberStyles.AllowThousands, null, 1000.0f };