Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #6787 > unrolled thread

Re: float("nan") in set or as key

Started byCarl Banks <pavlovevidence@gmail.com>
First post2011-05-31 23:09 -0700
Last post2011-06-01 18:29 +0000
Articles 4 — 4 participants

Back to article view | Back to comp.lang.python


Contents

  Re: float("nan") in set or as key Carl Banks <pavlovevidence@gmail.com> - 2011-05-31 23:09 -0700
    Re: float("nan") in set or as key "OKB (not okblacke)" <brenNOSPAMbarn@NObrenSPAMbarn.net> - 2011-06-01 17:17 +0000
    Re: float("nan") in set or as key Ethan Furman <ethan@stoneleaf.us> - 2011-06-01 11:10 -0700
      Re: float("nan") in set or as key Chris Torek <nospam@torek.net> - 2011-06-01 18:29 +0000

#6787 — Re: float("nan") in set or as key

FromCarl Banks <pavlovevidence@gmail.com>
Date2011-05-31 23:09 -0700
SubjectRe: float("nan") in set or as key
Message-ID<d63a1808-e704-4538-8541-9edeadab2135@glegroupsg2000goo.googlegroups.com>
On Tuesday, May 31, 2011 8:57:57 PM UTC-7, Chris Angelico wrote:
> On Wed, Jun 1, 2011 at 1:30 PM, Carl Banks 
>  wrote:
> > I think you misunderstood what I was saying.
> >
> > It's not *possible* to represent a real number abstractly in any digital computer.  Python couldn't have an "abstract real number" type even it wanted to.
> 
> True, but why should the "non-integer number" type be floating point
> rather than (say) rational?

Python has several non-integer number types in the standard library.  The one we are talking about is called float.  If the type we were talking about had instead been called real, then your question might make some sense.  But the fact that it's called float really does imply that that underlying representation is floating point.


> Actually, IEEE floating point could mostly
> be implemented in a two-int rationals system (where the 'int' is
> arbitrary precision, so it'd be Python 2's 'long' rather than its
> 'int'); in a sense, the mantissa is the numerator, and the scale
> defines the denominator (which will always be a power of 2). Yes,
> there are very good reasons for going with the current system. But are
> those reasons part of the details of implementation, or are they part
> of the definition of the data type?

Once again, Python float is an IEEE double-precision floating point number.  This is part of the language; it is not an implementation detail.  As I mentioned elsewhere, the Python library establishes this as part of the language because it includes several functions that operate on IEEE numbers.

And, by the way, the types you're comparing it to aren't as abstract as you say they are.  Python's int type is required to have a two's-compliment binary representation and support bitwise operations.


> > (Math aside: Real numbers are not countable, meaning they 
> > cannot be put into one-to-one correspondence with integers.
> >  A digital computer can only represent countable things
> > exactly, for obvious reasons; therefore, to model
> > non-countable things like real numbers, one must use a
> > countable approximation like floating-point.)
> 
> Right. Obviously a true 'real number' representation can't be done.
> But there are multiple plausible approximations thereof (the best
> being rationals).

That's a different question.  I don't care to discuss it, except to say that your default real-number type would have to be called something other than float, if it were not a floating point.


> Not asking for Python to be changed, just wondering why it's defined
> by what looks like an implementation detail. It's like defining that a
> 'character' is an 8-bit number using the ASCII system, which then
> becomes problematic with Unicode.

It really isn't.  Unlike with characters (which are trivially extensible to larger character sets, just add more bytes), different real number approximations differ in details too important to be left to the implementation.

For instance, say you are using an implementation that uses floating point, and you define a function that uses Newton's method to find a square root:

def square_root(N,x=None):
    if x is None:
        x = N/2
    for i in range(100):
        x = (x + N/x)/2
    return x

It works pretty well on your floating-point implementation.  Now try running it on an implementation that uses fractions by default....

(Seriously, try running this function with N as a Fraction.)

So I'm going to opine that the representation does not seem like an implementation detail.


Carl Banks

[toc] | [next] | [standalone]


#6807

From"OKB (not okblacke)" <brenNOSPAMbarn@NObrenSPAMbarn.net>
Date2011-06-01 17:17 +0000
Message-ID<Xns9EF768C113385OKB@88.198.244.100>
In reply to#6787
Carl Banks wrote:

> On Tuesday, May 31, 2011 8:57:57 PM UTC-7, Chris Angelico wrote:
>> On Wed, Jun 1, 2011 at 1:30 PM, Carl Banks  wrote:
>> > I think you misunderstood what I was saying.
>> >
>> > It's not *possible* to represent a real number abstractly in any
>> > digita 
> l computer.  Python couldn't have an "abstract real number" type
> even it wanted to.
>> 
>> True, but why should the "non-integer number" type be floating
>> point rather than (say) rational? 
> 
> Python has several non-integer number types in the standard
> library.  The one we are talking about is called float.  If the
> type we were talking about had instead been called real, then your
> question might make some sense.  But the fact that it's called
> float really does imply that that underlying representation is
> floating point. 

    	That's true, but that's sort of putting the cart before the horse.  
In response to that, one can just ask: why is this type called "float"?  
Why is it that when I type 1.37 or sqrt(2) in my program, the resulting 
object is a "float" rather than some other numeric type?  I'm aware 
that there are answers to this having to do with standardization and 
efficiency.  But I do sometimes wish that the "default" type for non-
integers (as created through Python expressions) was something more like 
"rationals with a denominator no bigger than N".

-- 
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is
no path, and leave a trail."
	--author unknown

[toc] | [prev] | [next] | [standalone]


#6812

FromEthan Furman <ethan@stoneleaf.us>
Date2011-06-01 11:10 -0700
Message-ID<mailman.2376.1306950997.9059.python-list@python.org>
In reply to#6787
Carl Banks wrote:
> For instance, say you are using an implementation that uses
 > floating point, and you define a function that uses Newton's
 > method to find a square root:
> 
> def square_root(N,x=None):
>     if x is None:
>         x = N/2
>     for i in range(100):
>         x = (x + N/x)/2
>     return x
> 
> It works pretty well on your floating-point implementation.
 > Now try running it on an implementation that uses fractions
 > by default....
> 
> (Seriously, try running this function with N as a Fraction.)

Okay, will this thing ever stop?  It's been running for 90 minutes now. 
  Is it just incredibly slow?

Any enlightenment appreciated!

~Ethan~

[toc] | [prev] | [next] | [standalone]


#6813

FromChris Torek <nospam@torek.net>
Date2011-06-01 18:29 +0000
Message-ID<is60e101pr7@news4.newsguy.com>
In reply to#6812
>Carl Banks wrote:
>> For instance, say you are using an implementation that uses
> > floating point, and you define a function that uses Newton's
> > method to find a square root:
>> 
>> def square_root(N,x=None):
>>     if x is None:
>>         x = N/2
>>     for i in range(100):
>>         x = (x + N/x)/2
>>     return x
>> 
>> It works pretty well on your floating-point implementation.
> > Now try running it on an implementation that uses fractions
> > by default....
>> 
>> (Seriously, try running this function with N as a Fraction.)

In article <mailman.2376.1306950997.9059.python-list@python.org>
Ethan Furman  <ethan@stoneleaf.us> wrote:
>Okay, will this thing ever stop?  It's been running for 90 minutes now. 
>  Is it just incredibly slow?

The numerator and denominator get very big, very fast.

Try adding a bit of tracing:

        for i in range(100):
            x = (x + N/x) / 2
            print 'refinement %d: %s' % (i + 1, x)

and lo:

    >>> square_root(fractions.Fraction(5,2))
    refinement 1: 13/8
    refinement 2: 329/208
    refinement 3: 216401/136864
    refinement 4: 93658779041/59235012928
    refinement 5: 17543933782901678712641/11095757974628660884096
    refinement 6: 615579225157677613558476890352854841917537921/389326486355976942712506162834130868382115072
    refinement 7: 757875564891453502666431245010274191070178420221753088072252795554063820074969259096915201/479322593608746863553102599134385944371903608931825380820104910630730251583028097491290624
    refinement 8: 1148750743719079498041767029550032831122597958315559446437317334336105389279028846671983328007126798344663678217310478873245910031311232679502892062001786881913873645733507260643841/726533762792931259056428876869998002853417255598937481942581984634876784602422528475337271599486688624425675701640856472886826490140251395415648899156864835350466583887285148750848

In the worst case, the number of digits in numerator and denominator
could double on each pass, so if you start with 1 digit in each,
you end with 2**100 in each.  (You will run out of memory first
unless you have a machine with more than 64 bits of address space. :-) )

-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W)  +1 801 277 2603
email: gmail (figure it out)      http://web.torek.net/torek/index.html

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web