-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Description
Parsing large floating-point numbers sometimes produces a number that differs from the correct value by one bit.
In particular, "6250000000000000000000000000000000e-12" produces this error.
The problem is illustrated in this sharplab.io sample
Let @double = double.Parse("6250000000000000000000000000000000e-12", NumberStyles.Any).
The first indication of the parsing problem is that the default string representation of @double is "6.250000000000001E+21" (note an extra 1 at the end).
The (little-endian) byte-representation (obtained with e.g. BitConverter.GetBytes) is
"F74AE1C7022D7544".
This representation is unfortunately incorrect.
The value 6.25e21 can be represented more accurately by a double-precision variable, and the byte-representation of this value is in fact
"F64AE1C7022D7544".
The difference (for this particular number) is one bit (F6 vs F7).
The mentioned above sharplab sample nicely illustrates this problem.
This issue was discovered when dotnet's parsing methods were run against a large set of floating point tests provided in this repository
https://github.com/nigeltao/parse-number-fxx-test-data
The test case discussed in this issue is found in data/ibm-fpgen.txt, line 64724
Details
7C00 63A96816 44752D02C7E14AF6 6250000000000000000000000000000000e-12There may be other (similar) issues, which I have not found yet.
Configuration
So far tested on Windows 10 x64 20H2 19042.804
-
dotnet @ Windows:
- 5.0.103
- 6.0.100-preview.1.21103.13
-
dotnet @ WSL2:
- 5.0.103
Whatever backend sharplab.io uses also reproduces this error.
Regression?
Did not test earlier versions of dotnet.
Other information
This report would not be possible without https://github.com/nigeltao/parse-number-fxx-test-data project and its contributors.
I verified this particular parsing case against Rust implementation, see this rust demo.
Maybe related to #48119
Partially inspired by discussion around #48646.