How safe is a set of floats?

Paul McGuire ptmcg at austin.rr.com
Fri May 4 12:04:10 EDT 2007


On May 4, 9:50 am, a... at mac.com (Alex Martelli) wrote:
> Thomas Nelson <t... at mail.utexas.edu> wrote:
> > I want to generate all the fractions between 1 and limit (with
> > limit>1) in an orderly fashion, without duplicates.
>
> > def all_ratios(limit):
> >     s = set()
> >     hi = 1.0
> >     lo = 1.0
> >     while True:
> >         if hi/lo not in s:
> >             s.add(hi/lo)
> >             yield (hi,lo)
> >         hi += 1
> >         if hi/lo > limit:
> >             lo += 1
> >             hi = lo
>
> > I use a set to keep from giving duplicates; but is this safe?  In C
> > they always tell you not to trust floating point equality comparisons,
> > since they may not work as you expect.  My code seems fine for the
> > limited amount I've tested, but I'm curious: is there a gaurantee
> > about sets of floats?  Or a warning?
>
> sets of floats work exactly like sets of anything else and thus in
> particular they DO intrinsically rely on == comparisons, i.e., exact
> equality checks (just like dicts whose keys are floats, etc).
>
> In your code, some "fractions" that actually differ from others you're
> previously seen will in fact be skipped because they don't differ _by
> enough_ -- i.e. they do compare == to within the limited precision of
> floating-point computations.  But if you do want to be yielding floats,
> and never want to yield the (num, denom) tuples for two items that *as
> float* compare ==, there's nothing you can do about that issue.
>
> My main suggestion to you actually would be to compute hi/lo ONCE per
> iteration rather than 3 times -- I detest repetition in principle and
> here it may be costing you a few nanoseconds' speed:-)
>
> [[If you don't truly care about whether the fractions you yield do
> compare as == "as floats", you might e.g. use gmpy.mpq rather than
> division to perform your checks]]
>
> Alex- Hide quoted text -
>
> - Show quoted text -

Does set membership test for equality ("==") or identity ("is")?  I
just did some simple class tests, and it looks like sets test for
identity.  So if I were to create a Rational class in which
Rational(1,2) and Rational(2,4) both evaluate to 0.5, such that
Rational(1,2) == Rational(2,4) evaluates to True, a set of such
Rationals would still hold both instances.

-- Paul





More information about the Python-list mailing list