This probably came up, but I would like to ask (again):
0.1 * 0.2 // == 0.020000000000000004
Looks like Elm inherits those problems. Is this intentional or are there plans to correct those errors at some point?
Fixing this for all floating point calculations is not feasible as it would slow down calculations a lot.
Solution here is to use separate Decimal type in those calculations which require exact math. There seems to be at least prikhi/decimal package for Elm which does this. (I havn’t used this, I just searched for Decimal packages in Elm.)
This is the result of floating point numbers.
Here is one of many sites that explain why this happens:
As mentioned by other commenters, this is common among all languages that use IEEE 754 floating-point numbers—that is to say, all languages that run on modern computers.
The reason for this is that IEEE 754 has been implemented at the hardware level, right down to the tricky
NaN /= NaN behavior. That’s basically why we can’t fix it: creating an alternate system means skipping over all those hardware optimizations using this system. In effect, to get away from these issues we’d either need to create a much slower numeric computation stack or make our own hardware. Neither of those is particularly tenable!
IEEE 754 standard actually does include decimal floating-point types since 2008 (fairly new addition, given that original standard is from 1985), and some hardware (e.g. IBM Power processors) does support them - but unfortunately not the common PC processors from Intel or AMD.
Some discussion here: Why isn’t decimal floating-point (DFP) from the IEEE 754-2008 already implemented in hardware of all modern CPUs by now?.
Whoah, that’s neat! Thanks for adding that.
As people have mentioned, this is a problem with floating point. That said, it isn’t unique to floating point either. Even if you do math with a decimal library you’ll get rounding errors. Consider
10 * (2/3) = 0.6666666...and forever except we can’t represent an infinite number of 6’s so it gets rounded to something like 0.6666667.
Thank you all for the answers.
I understand the issue better now.
I think a simpler solution than switching to a decimal or rational type (which would also be much lower performance than IEEE-754 doubles) is to use plain
Float values and use something like myrho/elm-round to control the number of decimal places used when displaying those values.
You’ll also need to avoid trying to compare two
Float values for equality using
== - either compare within some small tolerance, or (even better) avoid equality comparisons entirely. It can be very hard to come up with a good tolerance value, and speaking as someone who’s spent most of their career working on scientific/numerical code I find that it’s usually possible to restructure the code in a way that doesn’t need equality checks (and that’s usually a cleaner and more robust solution).
There are a couple packages in the repo for arbitrary-precision. You could explore them if you like. Search for “arbitrary precision”, however that sort of thing is not performant in the way you probably want. Have fun!
This is why elm-test suggests the assertions on floating point “equality” are given with some tolerance.
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.