On 17/06/2015 11:37, Eric Meadows-Jönsson wrote:
> The Kernel.to_string and Float.to_string functions have different
> goals and use cases. Float.to_string is for serialization, a more
> accurate way of printing a floating point number than
> Kernel.to_string. If you want pretty printing you can use
> Kernel.to_string as you already found.
>
> This behaves like erlang (although we chose different function names
> and locations for the functions); erlang:float_to_string has the same
> output as Float.to_string.
Hi, I hadn't twigged about the existence of Kernel.to_string - thanks.
Perhaps it would be nice if it were mentioned in the Float.to_string docs?
However, the point is that Float.to_string is horrible (and NOT more
accurate). I can (nearly) see the point when you want a specified
precision and understand the implications, but I feel quite strongly
that the "no option" version of Float.to_string should be an alias to
Kernel.to_string.
Updated proposal:
- set Float.to_string/1 to be an alias to Kernel.to_string
I'm sensing further justification is needed here? If you look at the
evolution of this on the Erlang side you can see a frustrated email to
fix float output some years back. I can't find the subsequent
correspondence, but it seems as though a partial fix is implemented
based on mochiweb code in that we now have *two* float output functions:
a) proper/correct output through 'fwrite_g' but without control over
precision or format.
b) nasty (sometimes) incorrect output but with control over output
format and precision
In my opinion what is desirable is for the existing Float.to_string to
be completely removed and new output functions to be produced using the
fwrite_g digits (but re-implementing control over format/precision). I
would think this is arguably most desirable to push into OTP stdlib,
however, if there were appetite then I already published my
re-implementation of the original paper in Elixir and all it requires is
final output formatting in order to be a complete replacement for the
existing Float.to_string/2 ? I don't plan to finish this unless there
is interest to push this to Elixir core though?
Please, take the time to read the original paper on this stuff before
responding (There are a number of good followup papers to this one as well):
http://www.cs.indiana.edu/~dyb/pubs/FP-Printing-PLDI96.pdf
The issue is somewhat subtle and non obvious and I think some might
understand the issue back to front:
Essentially the core issue is that IEEE arithmetic stores "intervals",
not numbers. Many naive to_string implementations will instead output
one of the boundaries or centre of the range. Without much disagreement,
a better solution is to pick the shortest number representation (in the
output base) which falls into the given range. Another definition of
success is that we can round trip the conversion (caveat we stay within
the limits of double precision IEEE)
So for example, given the input number 1.2
- I can round trip this to string and back to float using "the correct
algorithm", ie Kernel.to_string
- I get all kinds of trouble if I use Float.to_string
Further reasons that the current erlang output is garbage is that we
only have around 15 significant figures of accuracy with IEEE doubles,
but erlang defaults to trying to output 20 decimal places... Even worse
the output control only lets us specify decimal places, so attempting to
get the output correct would seem to require several passes of doing a
trial conversion, parsing the string, then re-requesting the conversion
with updated decimal places... The algorithm used by fwrite_g completely
avoids all this trouble and has provably optimal output (it just lacks
control over format and precision)
Thanks for listening
Ed W