Float.close?(a, b, epsilon=0.0000001)

54 views
Skip to first unread message

Gavin Sinclair

unread,
Dec 23, 2010, 8:14:21 PM12/23/10
to facets-u...@googlegroups.com
Comparing two Floats is a general-purpose feature that could be added to Facets.  I've implemented it in two projects that I'm working on, and submit it for consideration.

Here is my code:

    class ::Float
      def Float.close?(a, b, epsilon=0.0000001)
        a, b = a.to_f, b.to_f
        if a.zero? or b.zero?
          # There's no scale, so we can only go on difference.
          (a - b).abs < @epsilon
        else
          # We go by ratio. The ratio of two equal numbers is one, so the ratio
          # of two practically-equal floats will be very nearly one.
          (a/b - 1).abs < epsilon
        end
      end
    end

I don't know any best practices about this kind of thing.  My implementation was preceded by some research on Google, but that's it.  I have unit tests, but they're for a different implementation and in my own testing library which hasn't seen public release (http://github.org/gsinclair/attest).

Given the go-ahead, I'm happy to fork, implement (with tests) and send pull request.  I'm equally happy for someone to take the code, or even just the idea, and make it happen.  Also, of course, the specifics of the implementation should be discussed if necessary.

Gavin

Trans

unread,
Feb 1, 2011, 9:26:37 AM2/1/11
to facets-u...@googlegroups.com
Thanks for the suggestion. I'm wondering if this is needed in light of Numeric#approx? which is:

  class Numeric
    def approx?(x, n=0.01)
      return(self == x) if n == 0
      (self - x).abs <= n
    end
  end

Does this implementation need improvement? Or do we need something else for Floats like your method?

The other question is, how do we choose the default value of epsilon?


Gavin Sinclair

unread,
Feb 26, 2011, 4:26:16 AM2/26/11
to facets-u...@googlegroups.com
Thanks for the suggestion. I'm wondering if this is needed in light of Numeric#approx?
I wasn't aware of that.  Oops.

In any case, though, I suspect comparison by ratio (relative comparison) is better than absolute comparison.  If some calculation results in some tiny number like 3.1E-15, then it's not really "equal" to 6E-15 because that's about twice as large.  But those two numbers would pass any absolute comparison with flying colours.

My implementation is therefore based on ratios, except where zero is concerned.


 The other question is, how do we choose the default value of epsilon?
No idea.  Experience, I guess.  Gotta find someone who has some.  It was experience that led me to believe that absolute comparisons are insufficient, though.

Trans

unread,
Dec 28, 2011, 10:18:20 AM12/28/11
to facets-u...@googlegroups.com
Just want to let you know that I finally took your advice and used ratios.

Gavin Sinclair

unread,
Dec 28, 2011, 5:33:16 PM12/28/11
to facets-u...@googlegroups.com
On Thu, Dec 29, 2011 at 2:18 AM, Trans <tran...@gmail.com> wrote:
Just want to let you know that I finally took your advice and used ratios.


Excellent!  Next time I'm doing some floating point hoo-ha, I won't need to reinvent the wheel.

It wasn't easy to find a best practices guide in plain language last time I looked, so hopefully this is a good approach. 
Reply all
Reply to author
Forward
0 new messages