Why does 'list_to_float' and 'float_to_list' give different results on different versions

Please tell me why the function gives different results on different versions

vsn 19.1 list_to_float(float_to_list(615.4896 / 100, [{decimals, 2}])).


vsn 24.2 list_to_float(float_to_list(615.4896 / 100, [{decimals, 2}])).



Different algorithm for rounding. AFAIK the 24.2 is more correct one (cc @DianaOlympos, but from “organoleptic check” 6.154 should be rounded to 6.15, no other decimal points should affect that), but in general it is quite hard topic to have proper rounding of floating points.


Indeed we changed the algorithm to display the pretty print in the shell.
Both are valid, but keep in mind that you are using two different algorithm here to translate a float to a string.

First you translate a string, 615.4896 to a float. Then you translate a string 100 to an integer. You then cast that int to a float, divide the two float, then translate that float to a string at float_to_list with the rules of {decimals, 2}, which may or may not be correct as they are libc implementation dependant (thanks the C standard), then you translate that string into a float again, with list_to_float.

Then you translate that float into a string again by “printing” to the shell, using a totally different algorithm, which changed in OTP24.

It happens that the new Ryu algorithm used in OTP 24 (and accessible through a BIF option in otp 25) is probably the most “correct” for our modern understanding of correctness. But after all these transformations, some of these being destructive of information, it is already a small miracle that you get something that is “correct”, for some definitions of “correct”.

Defining which round is right in that case depends on the libc, the implementation of the round trip, the precision of the double when it is recasted and the way we chose to round for the pretty printing.

In particular, this does not promise at all that you will get the same result as an output of the pretty print. It is totally possible that the original float and the one that you pretty print after this are different one, due to the way “floats” sample the space of reals.