Path: csiph.com!usenet.pasdenom.info!aioe.org!news.stack.nl!newsfeed.xs4all.nl!newsfeed1.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.006 X-Spam-Evidence: '*H*': 0.99; '*S*': 0.00; 'example:': 0.03; 'float': 0.07; 'plenty': 0.07; 'anders': 0.09; 'keys,': 0.09; 'objects,': 0.09; 'returns,': 0.09; 'way:': 0.09; 'cc:addr:python-list': 0.11; 'def': 0.12; 'times,': 0.14; '(both': 0.16; 'equivalence': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'nan': 0.16; 'objects.': 0.16; 'tuples,': 0.16; 'wrote:': 0.18; 'wed,': 0.18; 'module': 0.19; 'value.': 0.19; 'examples': 0.20; 'import': 0.22; 'cc:addr:python.org': 0.22; 'instance,': 0.24; 'cc:2**0': 0.24; 'define': 0.26; 'equivalent': 0.26; 'header:In-Reply-To:1': 0.27; 'chris': 0.29; 'am,': 0.29; 'message-id:@mail.gmail.com': 0.30; 'you?': 0.31; '"",': 0.31; '>>>>': 0.31; 'keyerror:': 0.31; 'second,': 0.31; 'struct': 0.31; 'up:': 0.31; 'file': 0.32; 'class': 0.32; 'there.': 0.32; '(most': 0.33; "can't": 0.35; 'except': 0.35; 'something': 0.35; 'case,': 0.35; 'equal': 0.35; 'objects': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'there': 0.35; 'false': 0.36; 'should': 0.36; 'two': 0.37; 'list': 0.37; 'list.': 0.37; 'generic': 0.38; 'that,': 0.38; 'anything': 0.39; 'recent': 0.39; 'expect': 0.39; 'sure': 0.39; 'skip:p 20': 0.39; 'most': 0.60; 'new': 0.61; 'simple': 0.61; 'first': 0.61; 'such': 0.63; 'serial': 0.72; 'jul': 0.74; 'subject:For': 0.78; '4:29': 0.84; 'algorithm,': 0.84; 'sets,': 0.84; 'careful': 0.91; 'to:none': 0.92; 'imagine': 0.93 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type; bh=dHn24FlM3S+lohL4rovGbxGA5cNKI8mlvRjScOclWDo=; b=FuhLTnzYsA0oO3DEKhEbkwJzD41Rw6C5gTmalUeunFhxbtTVETA+aHMMM34UdWPQE6 FYGrPvUAgS1cjueq4TFaFDQppwvs6mZdSGleKh3LgZlstqzcXzDX6ogQeX8W6+DZsoeb 1A1tL4JhjUuYbM+Od5qEBh2qfibtOxtW50d7GbanB7bBkYHj+jM6tXUER0smoXjQzefT Zas4HF/2gPFGi9oShDM0cpTMHkBrWXEPmX3wCJKe1RE/wVcq4qQEJtaWBfFzb3Xl2k4t MtfpoPzE3aVdDUahTfuDEAHsXDEkmkwAai1fC1A9l9MfpARdQypy8ucdG2vhQ967GGbg gHtg== MIME-Version: 1.0 X-Received: by 10.58.29.16 with SMTP id f16mr35834346veh.23.1404844938657; Tue, 08 Jul 2014 11:42:18 -0700 (PDT) In-Reply-To: <53BC38A0.7030100@jmunch.dk> References: <53BC05FB.4050707@jmunch.dk> <53BC38A0.7030100@jmunch.dk> Date: Wed, 9 Jul 2014 04:42:18 +1000 Subject: Re: NaN comparisons - Call For Anecdotes From: Chris Angelico Cc: "python-list@python.org" Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 60 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1404844945 news.xs4all.nl 2921 [2001:888:2000:d::a6]:40016 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:74199 On Wed, Jul 9, 2014 at 4:29 AM, Anders J. Munch <2014@jmunch.dk> wrote: > Chris Angelico wrote: >> For hash keys, float object identity will successfully look them up: > > > Except you can't expect to rely on object identity in most interesting > cases. > >>>> x = float('nan') >>>> import struct >>>> y = struct.unpack('>>> d[x] = "found" >>>> d[y] > > Traceback (most recent call last): > File "", line 1, in > KeyError: nan > > and also: > >>>> def f(): return float('inf')/float('inf') >>>> f() == f() > False >>>> f() is f() > False Neither of those examples is anything to do with object identity. In the first case, you pack the value and recreate an equivalent of the same type with the same value. In the second, you independently construct two floats with the same value. Both times, you have equivalence (both are NaN), but not identical objects. > Let me conjure up a simple example: > > | class Monitor(Thread): > | def run(self): > | old = self.get_current_value() > | while not self.Terminated: > | new = self.get_current_value() > | if new != old: > | print(time.asctime(), "changed to", new) > | old = new > | time.sleep(1) > > This is a completely generic change detection algorithm, and not a > "floating-point algorithm" in any way: It will work on strings, lists, sets, > anything that get_current_value returns, including non-NaN floats. You don't > need to know anything about floating-point representation to write or use > such an algorithm, why should you? It works on tuples, sets, lists, serial > port handles, module objects, pretty much anything you can imagine -- except > NaN floats. You also have to cope with objects that define __eq__ or __ne__. If you know that you have a monitor like that, then you make sure that the value is something comparable; there are plenty of reasons to have to be careful there. (Consider, for instance, what happens if get_current_value() returns a list. Mutating that list can change whether or not it's equal to something else.) ChrisA