for double and float: how about proper "almost equals"

785 views
Skip to first unread message

fishtoprecords

unread,
Jan 5, 2010, 11:53:40 PM1/5/10
to guava-discuss
One of the big problems that folks new to programming with float/
double is that == is really not what you want most of the time. It
works with most of the other native types, but usually, when you are
using floating point, you really want "essentially equal" or
asymptotic equal.

I've got a Java implementation built from an ACM paper, with some more
comments from the GNU folks. I'm not expert enough at numerical
analysis to be sure that its 100% correct, but perhaps the community
has the experts for that. Its only 25 or so lines of code.

Nikolas Everett

unread,
Jan 6, 2010, 7:21:38 AM1/6/10
to guava-...@googlegroups.com
I like Junit's treatment of this:  assert(double expected, double actual, double delta).  The delta lets you account for all kinds of roundoff errors.  I don't recall any time when I actually meant to check if two floating point numbers were equal.  I'm usually much more interested in checking within some tolerance.  I suppose if there is a paper about it then someone must want to do it.

--
guava-...@googlegroups.com.
http://groups.google.com/group/guava-discuss?hl=en
unsubscribe: guava-discus...@googlegroups.com

This list is for discussion; for help, post to Stack Overflow:
for help: http://stackoverflow.com/questions/ask
Use the tag "guava".


fishtoprecords

unread,
Jan 6, 2010, 9:34:29 PM1/6/10
to guava-discuss
Here is one link to one paper on the topic:

http://docs.sun.com/source/806-3568/ncg_goldberg.html

What Every Computer Scientist Should Know About Floating-Point
Arithmetic

Ray Conner

unread,
Jan 18, 2010, 6:17:40 PM1/18/10
to guava-discuss
That works for a unit test, because you know what you're expecting to
get, and how much difference is OK. It doesn't work so well if the
values being tested fall in an unknown range. For that you need to
test relative error, not absolute error.

The paper linked to by fishtoprecords covers that topic, although
maybe in more depth than most would like to see. On the other hand,
it's really, really easy to get something wrong if you don't know what
you're doing when working in floating point, especially if you're
doing serious number crunching. So I suggest slugging through it just
to get a feel for how complicated it really is. Note that the paper
only scratches the surface; you could easily fill a couple years of
graduate study on the topic.

One word of warning for the Java programmers out there; if you have a
float- or double-valued field, do NOT use a "is really close to" test
as part of .equals(). You should either use exact equality, or not
test the field at all. I can conceive of other equivalence relations
to use, but any use case would be necessarily a special case.

- Ray Conner

On Jan 6, 7:21 am, Nikolas Everett <nik9...@gmail.com> wrote:
> I like Junit's treatment of this:  assert(double expected, double actual,
> double delta).  The delta lets you account for all kinds of roundoff errors.
>  I don't recall any time when I actually meant to check if two floating
> point numbers were equal.  I'm usually much more interested in checking
> within some tolerance.  I suppose if there is a paper about it then someone
> must want to do it.
>

> On Tue, Jan 5, 2010 at 11:53 PM, fishtoprecords <pat22...@gmail.com> wrote:
> > One of the big problems that folks new to programming with float/
> > double is that == is really not what you want most of the time. It
> > works with most of the other native types, but usually, when you are
> > using floating point, you really want "essentially equal" or
> > asymptotic equal.
>
> > I've got a Java implementation built from an ACM paper, with some more
> > comments from the GNU folks. I'm not expert enough at numerical
> > analysis to be sure that its 100% correct, but perhaps the community
> > has the experts for that. Its only 25 or so lines of code.
>
> > --
> > guava-...@googlegroups.com.
> >http://groups.google.com/group/guava-discuss?hl=en

> > unsubscribe: guava-discus...@googlegroups.com<guava-discuss%2Bunsu...@googlegroups.com>

fishtoprecords

unread,
Jan 18, 2010, 8:46:52 PM1/18/10
to guava-discuss
On Jan 18, 6:17 pm, Ray Conner <ray.a.con...@gmail.com> wrote:
> One word of warning for the Java programmers out there; if you have a
> float- or double-valued field, do NOT use a "is really close to" test
> as part of .equals(). You should either use exact equality, or not
> test the field at all. I can conceive of other equivalence relations
> to use, but any use case would be necessarily a special case.

Yes, this is a good point. Folks expect that if
a.almostEquals(b) and b.almostEquals(c)
then a.almostEquals(c) which may or may not be true.

deltaAB = a -b
deltaBC = b - c

you may find that
delta a-c is very nearly twice either deltaAB or deltaBC

Floating point causes so much trouble, I often wish that float and
double were not in the languages and some sort of Currency was.

If you are doing more than trivial work with floating point, you need
to be very careful in your numerical analysis

Willi Schönborn

unread,
Jan 18, 2010, 9:09:38 PM1/18/10
to guava-...@googlegroups.com
On 19/01/2010 02:46, fishtoprecords wrote:
> On Jan 18, 6:17 pm, Ray Conner<ray.a.con...@gmail.com> wrote:
>
>> One word of warning for the Java programmers out there; if you have a
>> float- or double-valued field, do NOT use a "is really close to" test
>> as part of .equals(). You should either use exact equality, or not
>> test the field at all. I can conceive of other equivalence relations
>> to use, but any use case would be necessarily a special case.
>>
> Yes, this is a good point. Folks expect that if
> a.almostEquals(b) and b.almostEquals(c)
> then a.almostEquals(c) which may or may not be true.
>
> deltaAB = a -b
> deltaBC = b - c
>
> you may find that
> delta a-c is very nearly twice either deltaAB or deltaBC
>
> Floating point causes so much trouble, I often wish that float and
> double were not in the languages and some sort of Currency was.
>
If you have to deal with currencies, use integer or long and treat them
as cents.

Robert Konigsberg

unread,
Jan 18, 2010, 9:11:49 PM1/18/10
to guava-...@googlegroups.com
On Mon, Jan 18, 2010 at 8:46 PM, fishtoprecords <pat2...@gmail.com> wrote:
> On Jan 18, 6:17 pm, Ray Conner <ray.a.con...@gmail.com> wrote:
>> One word of warning for the Java programmers out there; if you have a
>> float- or double-valued field, do NOT use a "is really close to" test
>> as part of .equals(). You should either use exact equality, or not
>> test the field at all. I can conceive of other equivalence relations
>> to use, but any use case would be necessarily a special case.
>
> Yes, this is a good point. Folks expect that if
> a.almostEquals(b) and b.almostEquals(c)
> then a.almostEquals(c) which may or may not be true.
>
> deltaAB = a -b
> deltaBC = b - c
>
> you may find that
> delta a-c is very nearly twice either deltaAB or deltaBC
>
> Floating point causes so much trouble, I often wish that float and
> double were not in the languages and some sort of Currency was.

See joda-money: http://joda-money.sourceforge.net/

Pat Farrell

unread,
Jan 18, 2010, 9:22:30 PM1/18/10
to guava-...@googlegroups.com
If you have to deal with currencies, use integer or long and treat them as cents.

You are missing my point, and the point of this thread.
Floats are misused more often then they are used properly.

I know how to do money, but too many beginning to intermediate Java programmers have no clue.

The suggestion is to help folks do proper numerical processing when floats are really needed.

Sometimes equals() is not really what you want. 

Robert Konigsberg

unread,
Jan 18, 2010, 9:40:14 PM1/18/10
to guava-...@googlegroups.com
On Mon, Jan 18, 2010 at 9:22 PM, Pat Farrell <pat2...@gmail.com> wrote:
>> If you have to deal with currencies, use integer or long and treat them as
>> cents.
>
> You are missing my point, and the point of this thread.
> Floats are misused more often then they are used properly.

I don't believe that. I believe they are misused. But they're also
used quite properly, in nice, well functioning areas. I do it often. I
however might believe your assertion was correct for a certain class
of programmer, but I still don't have the data.

> I know how to do money, but too many beginning to intermediate Java
> programmers have no clue.
> The suggestion is to help folks do proper numerical processing when floats
> are really needed.
> Sometimes equals() is not really what you want.

Then I better know what I want, or else work under someone who does.

> This list is for discussion; for help, post to Stack Overflow instead:


> http://stackoverflow.com/questions/ask
> Use the tag "guava".
>
>

--
Robert Konigsberg
konig...@gmail.com

fishtoprecords

unread,
Jan 18, 2010, 9:52:15 PM1/18/10
to guava-discuss
> I do it often. I however might believe your assertion was correct for a certain class
> of programmer, but I still don't have the data.

I am not meaning to imply that all Java programmers misuse floating
point.

But in the past 12 years of using Java professionally, and in several
College courses that I have taught, I have found a large need to
correct some fundamental misunderstandings.

> Then I better know what I want, or else work under someone who does.

Then you are not in the same position as a lot of folks that I've
seen.

Back on topic, I believe that Guava would be better if it has a good
implementation of almostEquals() for floats and doubles.

Ray Conner

unread,
Jan 18, 2010, 11:29:19 PM1/18/10
to guava-discuss
BigDecimal is a clearer alternative (since you won't lose fractions of
cent, suffer from overflow, etc.), although not as performant. But we
are way off-topic.

On Jan 18, 9:09 pm, Willi Schönborn <w.schoenb...@googlemail.com>
wrote:

Ray Conner

unread,
Jan 18, 2010, 11:41:54 PM1/18/10
to guava-discuss
An implementation shouldn't be too hard, for someone familiar with the
subject. I'm 99% sure such a thing already exists somewhere with
sufficiently flexible licensing. Standard C code, in this area, should
port pretty much as-is.

Then, of course, one might want a test for angles being almost equals;
but I would personally draw the line there. No reason to get into
norms in this library.

- Ray Conner

Pat Farrell

unread,
Jan 19, 2010, 11:22:15 AM1/19/10
to guava-...@googlegroups.com
On Mon, Jan 18, 2010 at 11:41 PM, Ray Conner <ray.a....@gmail.com> wrote:
An implementation shouldn't be too hard, for someone familiar with the
subject. I'm 99% sure such a thing already exists somewhere with
sufficiently flexible licensing. Standard C code, in this area, should
port pretty much as-is.


Upthread, I offered my Java implementation of it. It would need a review by someone better at numerical methods than I am, but I implemented the code referenced in the articles.
Reply all
Reply to author
Forward
0 new messages