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