# Number tree (was: Re: proposed language change to int/int==float (was: PEP0238 lament))

Bengt Richter bokr at accessone.com
Thu Jul 26 20:30:12 EDT 2001

```On 25 Jul 2001 12:47:30 GMT, Marcin 'Qrczak' Kowalczyk <qrczak at knm.org.pl> wrote:

>26 Jul 2001 00:03:56 +1200, Paul Foley <see at below> pisze:
>
>>>   int < long < rational < float < complex
>>
>> Well, it could, I suppose, but that would be a good reason to avoid
>> Python :-)
>>
>> What it *should* look like is this:
>>
>>   int < long < rational
>>                        \
>>                         + < [real] < complex
>>                        /
>>                   float
>
>There are no real reals in programming. And Python's complex is as
>inexact as float.
>
>I don't understand you. What practical difference do these diagrams
>yield? What is wrong in *consequences* of Guido's and mine model
>
>What happens if you int to float in your model? Rational to float?
>
The trouble with these discussions is that common usage creates an
overloading of meanings for the words. Some of these things can be
talked about sensibly even if computers don't exist. Some can't.
>From the above,

Can: rational, real, complex (integer belongs here too)
Can't: int, long, float

Separating the abstract (A) world from the world of (R)representations, you get
a different diagram, with as many variations below the line as you can
imagine (I'm mixing in C types and common typedefs to illustrate the idea)

A[integer] <  A[rational]      <       A[real]    <     A[complex]
v            v                        v                v
-------v------------v------------------------v----------------v-----------
v            v                        v                v
R[integer]   R[rational]               R[real]        R[real],R[real]
v~ ~[5]      +---------v~ ~[6]        +~ ~[7]
long       R[i]/R[i]  float[3]     R[rational]
v            v         v              v
int64        R[i]     fsingle[4]   R[integer]
v
fdouble[1]
v
int32
v
fsingle[2]
v
int16,short
v
int8,char
v
(single bit)

R[i] is short for R[integer] above. Specifics re fp below relate to IEEE754:
[1] as 53-bit integer
[2] as 24-bit integer
[3] as 53-bit integer * 2^n where -1022<=n<=1023 (interpret -n as /2^n )
[4] as 24-bit integer * 2^n where -126<=n<=127   (ditto)
[5] I show a wiggly side branch, because there's a zillion possible other ways
to represent integers. Python's long internally makes use of 15-bit integers,
I think I read in a post of Tim's, so it's really off to the side if you
like to think in terms of more traditional C representation types.
I included the floats at [1] and [2] just to illustrate possible variety.
[6] I added this to point out that you can/must interpret floating point numerical states
as representations of particular exact A[rational] numbers, and these exact
A[rationals] also serve as approximations to A[reals] (which can be right on or not)
represented as R[rational] under R[real]. BTW, "A[float]" is a way of referring to
the peculiar subset of A[rational] representable by concrete float states.
[7] On this branch, you could imagine various schemes for representing irrational
numbers, such as rationals with stored rational exponents, and special
representations for e and pi etc., etc.

By R[integer] etc., I mean representation in the widest sense that can have a
concrete realization. E.g., we could imagine representing really big integers
by combining the distributed resources on the internet. The point is, what's
below the line has no significance mathematically until you translate it back
to something above the line using some mapping you have in mind.

Computers have been designed to transform stuff below the line. They can't touch
stuff above the line. They can only produce stuff that may have a relationship
to what's above. It's pretty obvious if you think about it, but it's easy to
lose sight of in daily shortcut habits of thought.

Maybe our discussions would become clearer if we adopted a convention to indicate
which aspect of a number we were talking about, e.g., A[x] for the abstraction
behind our mention of x, and R[x] for some corresponding representation. If you
want to indicate a specific type of representation, it could be R[type:x], e.g.,
R[float:x]

Saying that "there are no real reals in programming" is really saying
A[real] != R[real], but that doesn't mean that we can't deal with A[problems]
with A[real] functions by using R[real] approximations.

Without [7] we can do no better than R[rational] under R[real], which is why
I didn't elaborate the tree. Note that R[rational] includes float at [3].
Decimal floats or any other monster float you can come up with will ultimatlely also
attach at [6].

Anyway, this is the way I look at it ;-)

Maybe with Guido and Tim's help, and that of lurking mathematicians, something like
the above could become a useful part of Python docs.

It would be nice to work in exact vs inexact also. Obviously, any R[] is exactly
something, because it has a particular distinct state, so there is an A[x] for every R[x].
Thus every R[x] has the possibility of serving as an exact representation (i.e., of A[x]).
But I think I'll stop here, because exactness and all that is too big a discussion.

HTH make discussions more meaningful ;-)

```