diff options
author | github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> | 2021-02-28 03:50:33 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-28 03:50:33 +0300 |
commit | ae5d71611b274f9bab047932037adfc16c1199c1 (patch) | |
tree | 77edb6bfae7b40e8fe97ffb4ff3e148dc92927d6 | |
parent | ec21beea1763aa539e1084e595a86a58d444036e (diff) |
[release/6.0-preview2] Track trailing zeros only for floating point numbers (#48857)
* Track trailing zeros only for floating point numbers
* Undo previous unit test change
* Add a roundtrip unit test
* Move check outside the loop
* Globalization
* Also fix #48648 and unit tests
* Assert and unit test
Co-authored-by: Prashanth Govindarajan <prgovi@microsoft.com>
7 files changed, 53 insertions, 15 deletions
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 88cb2f0ee95..b9cc53ceb23 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 @@ namespace System.Formats.Cbor.Tests [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 a07153cad25..382eb1ccf82 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 @@ namespace System { 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 @@ namespace System } 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 @@ namespace System 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 @@ namespace System [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 e4f3c9d8012..35069a81e61 100644 --- a/src/libraries/System.Runtime/tests/System/DecimalTests.cs +++ b/src/libraries/System.Runtime/tests/System/DecimalTests.cs @@ -1500,6 +1500,14 @@ namespace System.Tests Assert.Throws<FormatException>(() => 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<object[]> 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 8403fe131d6..d0bfcfb4141 100644 --- a/src/libraries/System.Runtime/tests/System/DoubleTests.cs +++ b/src/libraries/System.Runtime/tests/System/DoubleTests.cs @@ -290,6 +290,13 @@ namespace System.Tests 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 e851f28815f..926034b5b70 100644 --- a/src/libraries/System.Runtime/tests/System/HalfTests.cs +++ b/src/libraries/System.Runtime/tests/System/HalfTests.cs @@ -685,6 +685,11 @@ namespace System.Tests 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 f64df4bcc31..fca800ca292 100644 --- a/src/libraries/System.Runtime/tests/System/Int32Tests.cs +++ b/src/libraries/System.Runtime/tests/System/Int32Tests.cs @@ -355,6 +355,12 @@ namespace System.Tests 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 1fa4916c172..962621d05c1 100644 --- a/src/libraries/System.Runtime/tests/System/SingleTests.cs +++ b/src/libraries/System.Runtime/tests/System/SingleTests.cs @@ -295,6 +295,12 @@ namespace System.Tests 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 }; |