[Proposal] Add a Float.nearly_equal? function.

108 views
Skip to first unread message

Eamonn O'Brien

unread,
May 19, 2021, 6:21:32 PM5/19/21
to elixir-lang-core
Hi All,

My first post here, so hello all and thanks for all the great work on Elixir so far!

This is a relatively simple proposal. Many of the Float functions already take precisions and, floating point arithmetic being what it is a comparison function that takes some sort of epsilon value is almost required for a lot of floating point work.

As https://floating-point-gui.de/errors/comparison/ outlines writing such a function is both tricky and error prone so adding an implementation of that function to the core library makes sense.

I would propose a spec something like:

@spec nearly_equal?(float, float, precision) :: bool

Using an epsilon value instead of a precision might make more sense in some contexts but since the rest of the functions in Float use a precision value that is probably more consistent.

Arguments for:

The documentation for Float already links to the above article discussing why such a function might be needed. Adding an implementation probably makes sense.

It is a sufficiently widely used function that a default implementation in the standard library is not going to be clutter.

It is a tricky function to get right and providing a default implementation would be beneficial.

Having it available might make devs more likely to use it instead of comparison or pattern matching floats.

Arguments against:

The function can already be written using the tools provided in the core language. Implementation of such a function is not necessary and arguably is something domain specific that should be written per project.

It doesn't behave very well with pattern matching. This could of course be rectified by making it usable as a function clause ala:

def float_stuff(x, y) when nearly_equal?(x, y, 5), do ...

There may be a copyright issue with just writing a version of the code linked.

Alternatives:

Using the same spec but calling the function equal? and defaulting precision to 15 might make more sense.

José Valim

unread,
May 20, 2021, 3:31:17 AM5/20/21
to elixir-l...@googlegroups.com
Thanks Eamonn for sharing! The article and its references led to very interesting reading.

In principle I don't see an issue with adding such a function, but I believe we need to survey other languages and see what they are calling it and which edge cases they consider too.

Using the code above may be ok at the end, it is under Creative Commons, but we need to survey around before. :)

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/23f8e3a6-0aa6-426c-bb67-497a6bd7bf66n%40googlegroups.com.

Allen Madsen

unread,
May 20, 2021, 9:09:20 AM5/20/21
to elixir-l...@googlegroups.com

Christopher Keele

unread,
May 20, 2021, 11:12:20 PM5/20/21
to elixir-lang-core
> It doesn't behave very well with pattern matching. This could of course be rectified by making it usable as a function clause ala:
> def float_stuff(x, y) when nearly_equal?(x, y, 5), do ...

I wanted to see if the algorithm described in the linked article was possible to implement as a guard, and indeed it is! (More readable non-guard version here.)

Mind you I approached this as a fun guard exercise and it needs way more scrutiny:
  • We should review other langs and algos deeper.
  • My choices of function and variables names were not thought through.
  • I cribbed both the constants and the test suite straight from the Java implementation linked in the article.
    • That means that if the constants are not correct for the BEAM, the tests would not necessarily reveal this;
    • Someone more BEAM-float-literate than I would need to verify them.
---

The author also tantalizingly alludes to another more accurate approach, that requires

> the programming language to support conversion between floating-point values and integer bit patterns

Of course, we do, so I might check out the fairly long linked paper and play with that approach! It might not be possible to implement as a guard though, have to do more reading.

Christopher Keele

unread,
May 20, 2021, 11:17:10 PM5/20/21
to elixir-lang-core
Meant to deep-link to the constants in question. I defined them here, derived from the Java constants that the author used (documented here, here, and here).
Reply all
Reply to author
Forward
0 new messages