Why 1234.6 * 100 result is 123459.99999999999

Erlang/OTP 24 [erts-12.3.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]

Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 1234.6 * 10
12346.0
iex(2)> 1234.6 * 100
123459.99999999999
iex(3)>

Please help to clarify or any link/documents to aware about that?

1 Like

I searched a blog: Arbitrary-precision arithmetic in Erlang and Elixir | by Maxim Molchanov | Medium

1 Like

The blog post you found explains the phenomenon well. For future reference, the number section in the Erlang reference manual also explains why floats print the way they do.

2 Likes

Has this improved in OTP25 with the new float_to_list implementation? If not, would using [shortest] by default for ~p be an acceptable change?

1 Like

Such is the nature of binary floating-point arithmetic.
ok@tarski:~/Downloads$ python3
Python 3.6.9 (default, Mar 15 2022, 13:55:28)
[GCC 8.4.0] on linux
Type “help”, “copyright”, “credits” or “license” for more information.

1234.6 * 100
123459.99999999999

3 Likes

Here’s a floating point converter tool to play around with. Try even “simple” numbers like 0.1 and 0.01.

https://www.h-schmidt.net/FloatConverter/IEEE754.html

2 Likes

Generally you should avoid using float() in your applications. Floating point math performs much worse than integer math and leads to results which violate the principle of least astonishment.

Especially do not use floating point for monetary values. Money is commonly represented with decimal notation however that does NOT mean it should be stored as float(). Doing so will make your accountant very sad, he likes it when columns add up! Monetary amounts should be integer multiples of cents internally and converted to/from the human readable decimal form. If you require fractions of cents then decide on a minimum unit (i.e. a thousandth of a cent). This way performance is better and math actually works the way you expect it to.

4 Likes

Integer arithmetics makes everything complicated where you need to perform a division. You can also not properly interpolate etc. pp.

Floats are perfectly fine as long as you round in the right places (or use the new shortest representation :)) and ensure that your calculations stay well below the accuracy limits of 64bit doubles. I have been developing and operating an algorithmic energy trading application in Erlang for 10 years, and we never had a single(!) issue with float arithmetic, neither with middle nor back office, since seitching exclusively to float arithmetics about 7 years ago.

2 Likes

afaict, ~p should already be using [shortest] in OTP25 as it calls it under the hood. If it is not the case, it is a bug.

1 Like