[gambit-list] API to parse floats in Scheme
Marc Feeley
feeley at iro.umontreal.ca
Wed May 12 17:28:48 EDT 2021
> On May 12, 2021, at 3:43 PM, Lassi Kortela <lassi at lassi.io> wrote:
>
> We are planning a simple SRFI to mae floats from integers (or from strings), since that's useful when parsing any kind of text syntax that has real numbers. The details are implementation-dependent and tricky to get right.
>
> Here's the spec we have so far: https://github.com/pre-srfi/make-float
>
> The API is:
>
> (inexact-real-from-strings int frac precision exp) -> real
> (inexact-real-from-integers int frac frac-length precision exp) -> real
>
> Example usage:
>
> (inexact-real-from-strings "-123" "45" 'e "6") ; => -123.45e6
> (inexact-real-from-integers -123 45 2 'e 6) ; => -123.45e6
>
> The 2 in the last example means two decimal places. It's needed to disambiguate between .6 .06 .006 .0006 etc.
>
> There are both math and Scheme wizards on this list. Could someone verify whether this is a sane design before we submit the SRFI draft? It's been ok'd by one mathematician already so I'm hopeful :)
>
> There's also an inverse API to serve as a backend for string formatting packages:
>
> (strings-from-inexact-real real frac-length) -> int; frac; exp
> (integers-from-inexact-real real frac-length) -> int; frac; exp
A few things that come to mind:
1) The procedure inexact-real-from-integers can’t create negative zero. Perhaps the sign should be separate from the “int” part.
2) In the code I have written in the past to convert strings to numbers all of the digits are accumulated in a single integer and the number of decimals is kept separately (your fac-length). The parameters “int” and “frac” could be combined into one. By doing this the frac-length and exp can also be combined.
3) I don’t see provisions to parse +/- infinity and nan.
4) Many languages now allow “_” in the digits, so it is not clear how this fits into your API. Maybe an extra parameter indicating the allowed separator (with a default of #f meaning no separator allowed).
5) The API for the procedure inexact-real-from-strings is not ideal to implement something like string->number, because there will be some calls to “substring” to extract each part. This will be slow and generate garbage. It would be better to have an API where the number of calls to “substring” can be minimized. For example the API could be a single procedure where the sign, int and exp parts can be a string, symbol or integer. Trailing parameters could be optional with a default of 0. Something like this:
(make-inexact-real sign int exp precision)
(make-inexact-real '- 0) ;; => -0.0
(make-inexact-real '+ 123 -2) ;; => 1.23
(make-inexact-real "+" "123" 10 'e) ;; => 1.23e12
You can always do
(make-inexact-real "-" (string-append "123" "45") (- 6 2) 'e)
instead of (inexact-real-from-strings "-123" "45" 'e "6")
Marc
More information about the Gambit-list
mailing list