This tracks essentially all the IEEE 754:2008 requirements:
Positive Zero
Negative Zero
Positive Infinity
Negative Infinity
Quiet NaN
Signalling NaN
Finite (non-zero) Numbers
M digits, where M=17 for double and M=9 for singleH, if any, on significant digits converted must be >= M + 3 (20 for double and 12 for single)H digits are requested must be padded with zerosH digits must be correctly rounded to H digits and then convertedCC. @danmosemsft, @jkotas
Completed: ~Negative Zero should be covered by https://github.com/dotnet/coreclr/pull/19775~
Negative/Positive infinity are interesting as today we produce the unicode ∞ symbol, while the spec requires us to produce (and support) inf or infinity (case-insensitive)
NaN should be trivial if we don't want to support the optional parts, we just need to change the parsing to case insensitive, and also support "snan" being recovered to double.NaN
The Finite Numbers section shouldn't be overly complicated to support, as our existing implementation should handle it all correctly. We should just need to increase the "limits" defined in a few places
For both parsing and formatting values we use the IFormatProvider given (which defaults to CurrentInfo.
I would presume the desired direction is to always strictly follow the IFormatProvider given and to ensure that NumberFormatInfo.InvariantInfo is strictly IEEE compliant. For English, this will mean that the default provider is non-IEEE compliant. However, InvariantInfo will be compliant (and already does the right thing for the most part).
This would, for netcore3.0, result in the following new behavior...
When Formatting:
-0.0 for double, float, and decimal)When Parsing:
-0.0 for double, float, and decimal)NaNSymbol, PositiveInfinitySymbol, and NegativeInfinitySymbol will be parsed as OrdinalIgnoreCase (today it is parsed as Ordinal)Things to determine:
NaNSymbol, we need to determine what to do with snan, which we must support parsing, but which we can convert to double.NaNSNaNSymbol property, which defaults to NaNSymbol except on InvariantCulture where it would be "SNaN"NaN we need to determine if we want to support round-tripping the bit payload (which is considered optional per the IEEE spec)H) for all format specifiers or just for "R"DoubleToNumber currently supports 50 characters as its upper limit, and we can pad with zeros (as per the IEEE requirement) if someone asks for more.@Jkotas, @danmosemsft, @eerhardt. Thoughts on the above?
I would spin a separate issue for SNaN. It is a new public surface and it has the highest breaking potential from all of the above. It is not unusual to see checking for NaN by string comparison.
Closing this as the majority of issues have been addressed:
NaN payloads (which are optional according to the spec)SNaN: https://github.com/dotnet/coreclr/issues/21271SNaN to NaN (we do not have to preserve the signalling bit)SNaN correctly (we format to NaN, dropping the signalling bit as allowed)R to always return the shortest round-trippable string. There are a few papers on the subject here and this will provide a good balance between compliance and user-friendly outputsF, but not for ones like E or G