Skip to content

Floating point number parsing #1186

Closed
Closed
@cician

Description

@cician

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.

  1. The decimal number parsing from text.
  2. 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

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions