I need to parse floating-point literals in C code using OCaml.
OCaml’s float type is 64 bit. I have the string of the literal, its numeric value rounded to 64 bits and its kind (float, double or long double).
The problem are literals with a numeric value bigger than 64 bit:
- long double literals
- float literals with ‘f’-suffix for which double rounding errors would occur if they wouldn’t have the suffix.
OCaml’s arbitrary-precision module can parse rational numbers from strings like “123/123”, but not “123.123”, “123e123”, “0x1.23p-1” like they might appear in C.
Background: I do value analysis of C programs using CIL.
Double literals of any size and float literals with a numeric value that fits into 64 bit are always correctly represented. By rounding from double- to single-precision I can also reproduce double rounding errors.
I wrote my answer in the form of a blog post
To summarize some of the points here: you could interface
strtold()andstrtof()from OCaml. For the former, you would have to consider how you are going to store the result it produces, since there only is a point iflong doubleis larger thandoubleon your host architecture. There remains the problem that these functions are buggy in one of the most widely used C library. Very slightly buggy, but buggy for exactly the examples that are going to be of interest if you are doing this to study double rounding.Another way is to write your own function, starting from another post in the blog you refer to.
Finally, the phrase “Even getting single-precision floats right requires me to parse literals with values bigger than 64 bit” that you use in the comments is still a strange way to put it. The intermediate format(s) in which you can parse the representation of a single-precision float before you round it to single-precision have to be lossless, otherwise there will be double rounding. Double rounding may be more or less difficult to exhibit depending on the precision of the lossy intermediate format, but using 80 bits or 128 bits binary floating-point formats is not going to remove the problem, just make it more subtle. In the simple algorithm that I recommend, the intermediate format is a fraction of two multiprecision integers.