Description
Currently Grain doesn't have a way to parse floating point numbers.
I've started digging into it myself as part of #1133, but I'm still in early stages. I'm opening this issue to track progress and get some feedback.
The effort can be split in chunks and thus implemented in stages.
- The decimal number parsing from text.
- The conversion from decimal to floating point.
I am not considering localized or configurable number parsing here. Localization is currently not handled in stdlib and I think should be approached at a higher level. Instead I intend to implement a simple parseFloat
as the inverse of dtoa
, just like parseInt
is to itoa
.
It would only parse simple decimal numbers with period as decimal separator and exponential notation. No support for grouping separators or different decimal separator.
Should I implement both parseFloat64
and parseFloat32
or just the 64 bit version?
Btw, currently toString
of a Float32 converts to it f64 and then calls dtoa
, which isn't wrong, but may lead to some confusion when the additional precision shows up in the result compared to source number parsed from a decimal text, like a literal value in the code like this:
print(0.1d) // "0.1"
print(0.1f) // "0.10000000149011612"
(for more insight https://stackoverflow.com/questions/916081/convert-float-to-double-without-losing-precision)
Is this API good?
parseFloat64: (String) -> Result<Number,String>
String error case to conform with parseInt
.
Should it accept "NaN", "Infinity" and "-Infinity"? Most implementations do, but it may result in bugs.
Since I do not have deep knowledge about floats, the only way I could implement the part of conversion from decimal to float in a reasonable time, is by porting existing open source code. I find it easy enough to port .net code, which is implemented in C#, so high level enough for me to follow through. It's MIT licensed. There are of course other implementations I could port. For example the one in AssemplyScript, which looks a lot simpler, but I have no idea how good it is at handling rounding and various edge-cases so I'd go for a safer bet.
I'd need to port a significant portion of these files and maybe something more:
https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs
https://github.com/dotnet/runtime/blob/4017327955f1d8ddc43980eb1848c52fbb131dfc/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
https://github.com/dotnet/runtime/blob/4017327955f1d8ddc43980eb1848c52fbb131dfc/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Float.cs#L71
https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/Number.NumberBuffer.cs
AssemblyScript's for comparison:
https://github.com/AssemblyScript/assemblyscript/blob/d884ac8032b2bfa0caf26d4dc11d99c5a9543c13/std/assembly/util/string.ts#L771