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

double.TryParse converts small exponent to negative infinity in .NET Core 3.0+ #13806

Open
twsouthwick opened this issue Nov 19, 2019 · 8 comments
Labels
area-System.Numerics backlog-cleanup-candidate An inactive issue that has been marked for automated closure. documentation Documentation bug or enhancement, does not impact product or test code help wanted [up-for-grabs] Good issue for external contributors no-recent-activity
Milestone

Comments

@twsouthwick
Copy link
Member

I recently added .NET Core 3.0 to the test matrix for a project and two tests started failing, one having to do with double parsing, the other with float. It boils down to this:

Console.WriteLine(Environment.Version);
const string input = "-1.79769313486232e309";
Console.WriteLine($"Input: {input}");
var success = double.TryParse(input, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out var result);
Console.WriteLine($"double.TryParse: {success}: '{result}'");

On .NET Core 2.1, the output looks like this:

4.0.30319.42000
Input: -1.79769313486232e309
double.TryParse: False: '0'  

On .NET Core 3.0, the output looks like this:

3.0.0
Input: -1.79769313486232e309
double.TryParse: True: '-∞'

I know a number of changes went into .NET Core 3.0 regarding floating points, but this seems to be a regression. It's a small number, but I want to know if it's negative infinity or just too small to accurately fit within a double (same thing for value for float).

@twsouthwick
Copy link
Member Author

@tannergooding Since it appears you did most of the work for the floating point stuff

@tannergooding
Copy link
Member

This is by design. IEEE 754 specifies that operations are computed as if to infinite precision and unbounded range and then rounded to the nearest representable result.

"-1.79769313486232e309" as if to infinite precision and unbounded range is precisely "-1.79769313486232e309". It is greater than double.MinValue + Epsilon (where epsilon is the distance between x and its next representable value) so it rounds to -Infinity.

  • This cutoff is approx 1.7976931348623157e+308 + 1.9958403095347198e+292 = 1.797693134862315899584030953472e+308

Under the IEEE 754 spec, there isn't any value that can't be represented by a double/single. There are just values that are too large in magnitude or too small in magnitude. Values that are too large overflow to +/-Infinity and values that are too small underflow to +/-Zero.

@tannergooding
Copy link
Member

It might be interesting to expose a parsing API which allows you to detect maximum error for a value ( you can't necessarily represent exact error as a double/single) or if the parsing was precise.

This sounds like it would fit your use case and would allow programs to more readily account for this error if it was important..

@AntonLapounov
Copy link
Member

@tannergooding One issue here is that we introduce breaking changes without updating documentation:

https://docs.microsoft.com/en-us/dotnet/api/system.double.tryparse?view=netcore-3.0

The conversion fails if the s parameter is null or Empty, is not in a format compliant with style, represents a number less than MinValue or greater than MaxValue

According to the documentation, -∞ must fail the conversion.

@tannergooding
Copy link
Member

Yes, there are apparently a few places where various remarks/etc need to be updated. I've been updating them as I've been made aware of them as I don't believe we have a good way of tracking all the locations needing updated today.

@danmoseley
Copy link
Member

I don't believe we have a good way of tracking all the locations needing updated today.

It's not much help, but some queries like this seem to throw up not too many hits, if you didn't already look at those places.

https://github.com/dotnet/dotnet-api-docs/search?q=%22System.Double.MinValue%22&unscoped_q=%22System.Double.MinValue%22
https://github.com/dotnet/dotnet-api-docs/search?q=%22System.Double.NegativeInfinity%22&unscoped_q=%22System.Double.NegativeInfinity%22

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@jkotas jkotas added the documentation Documentation bug or enhancement, does not impact product or test code label Jan 31, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 23, 2020
@tannergooding tannergooding added area-System.Numerics and removed area-System.Runtime untriaged New issue has not been triaged by the area owner labels Jun 23, 2020
@ghost
Copy link

ghost commented Jun 23, 2020

Tagging subscribers to this area: @tannergooding
Notify danmosemsft if you want to be subscribed.

@tannergooding tannergooding added this to the Future milestone Jun 23, 2020
Copy link
Contributor

Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.

This process is part of our issue cleanup automation.

@dotnet-policy-service dotnet-policy-service bot added backlog-cleanup-candidate An inactive issue that has been marked for automated closure. no-recent-activity labels Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Numerics backlog-cleanup-candidate An inactive issue that has been marked for automated closure. documentation Documentation bug or enhancement, does not impact product or test code help wanted [up-for-grabs] Good issue for external contributors no-recent-activity
Projects
None yet
Development

No branches or pull requests

6 participants